代码随想录刷题记录之数组

143 阅读1分钟

代码随想录刷题记录

数组

二分查找基本题

题目:找target,关键字:升序,无重复元素,分三种情况讨论结构更清晰

var search = function(nums, target) {
    let l = 0, r = nums.length - 1;
    while(l<=r){
        let m = l + Math.floor((r-l)>>1);
        if(nums[m]>target){
            r = m - 1;
        }else if(nums[m]<target){
            l = m + 1;
        }else{
            return m;
        }
    }
    return -1;
};

二分查找提升题

题目:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 分析:有四种情形:

  • target比nums[0]小,那么插入的位置是0
  • target比nums[len-1],那么插入的位置是len-1,即最后一个位置
  • target存在数组中,比如5和[1,2,5,6],那么插入的位置就是index = 2.
  • target在两个元素之间,比如4和[1,3,5],那么插入的位置就是index = 2.
let l = 0, r = nums.length - 1;
    let ans=nums.length;
    while(l<=r){
        let m = l + Math.floor((r-l)>>1);
        if(nums[m]>target){
            r = m - 1;
            ans = m;
        }else if(nums[m]<target){
            l = m + 1;
        }else{
            return m;
        }
    }
    return ans;
};

这个题的重点是判断这四种情况返回值与middle的关系 除了第三种情况,其余返回的都是循环结束时候的m,第三种情况返回m+1;

先说方法:r指针移动的时候将m值存下来,ans=m,最后返回m,这样就满足了上述返回m和返回m+1的情况

ans的初值是nums.length,如果ans的值一直没有改变,说明一直移动的左指针,target大于最大值。

target小于nums[0]时,循环结束前r和l一定会来到nums[0]的位置,那么ans跟随r的变化也是0。

发现如果target不存在数组里面的话,l和r一定会在一个元素下相遇。

快慢指针

快慢指针一般用来不额外开辟内存,修改数组的值。

题目:删除数组中指定元素

雷区,记住返回return slow

var removeElement = function(nums, val) {
    let fast = 0, slow = 0;
    while(nums[fast]){
        if(nums[fast]!=val){
            nums[slow++]=nums[fast];
        }
        fast++;
    }
    return slow;
};

没有return slow返回的: 以[2,3,3,2],删除2为例,返回的是[3,3,3,2],因为slow指针走到了index=2的位置,有return slow相当于arr.slice(0,-(len-index)),删除后几项。

滑动窗口

题目:给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

重点:弄清楚左右指针什么时候移动。 右指针负责遍历。

左指针:when:当窗口内容满足要求时,where:左指针移动到哪个位置,与具体情境有关,基本题找满足target最小连续子串,则left++,找水果提升题,则是需要记录第一种水果结束的位置,作为下一次left移动的位置。

var minSubArrayLen = function(target, nums) {
    let l = 0, r = 0,sum=0;
    // 1.res初始值
    let res=nums.length+1;
    // 2.循环结束条件
    while(r<nums.length){
        sum+=nums[r++];
        // 3.这里得是while而不是if
        while(sum>=target){
            res = r-l < res ? r-l : res;
            sum-=nums[l];
            l++;
        }
    }
    return nums.length < res? 0:res;
};
  • 1.res初始值,万一循环结束也没有找到合适的子串,用res来判断
  • 2.循环结束条件:右指针到顶
  • 3.这里必须是while,写成if就错了,因为while的话,相当于固定了r,然后l移动,缩小窗口,看看有没有达到要求的窗口。