leetcode704二分查找&27移除元素&209长度最小的子数组

60 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

废话不多说,先摆上704代码

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){     //这个循环结构老是忘记写,而且是<=
            int mid = left + (right - left);
            if (target == nums[mid]){
                return mid;
            } else if(target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}
  • 关键的思想就是小了,右边界变成中间-1;大了,左边界变成中间+1;
  • 可以用迭代但是明显会慢一点,所以直接使用了个while循环进行判定,但是while循环我自己老是忘记写,要记得。如果没有左边界要小于等于右边界的话,就会出去然后报错。

27一开始卡住了,傻逼地认为还是需要弄个二分查找,做傻题目了吧

27这道题,这道题最优解法就是双指针,相当于用空间换时间。如果用暴力解法两层循环也行。数组有个特点就是创建后你删除某个元素,它所占据地空间还是在那,只能采用覆盖的方法。

Java代码如下:

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for(int fast = 0;fast < nums.length;fast++) {
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            } 
        }
        return slow;
    }
}

209这道题,先自己用了两层循环的滑动窗口导致超时了

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left =0;
        // int sum = 0
        int n = 100000;
        int right = 0;
        while(left < nums.length){
            int sum = 0;
            for(right = left;right < nums.length;right++){
                sum += nums[right];   //这里的先后顺序问题
                if(sum>=target){
                    int num = right - left + 1;
                    // return num;
                    if(n>num){
                        n = num;
                        // 看懂了,可恶,我没有加left,导致一直循环
                    }
                    break;
                }
            }
            left++;
        }
        return n == 100000 ? 0 : n;
    }
}

过了测试用例18个,但是专门检测是否超时的就卡住了。明天再看,再放正确解答上来

滑动窗口的精妙之处在于根据当前子数组和的大小,不断调节子数组的起始位置,从而将时间复杂度从O(n方)降为O(n)

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left =0;
        // int sum = 0
        int n = 1000000;
        int right = 0;
        int sum = 0;
        for(right = 0; right<nums.length;right++){
            sum += nums[right];
            while(sum>=target) {
                if(n>(right - left + 1)){
                    n = (right - left + 1);
                }
                sum -= nums[left++];   //这里是关键点,缩小窗口大小,也就是滑动窗口的核心。
            }
        }
        return n == 1000000 ? 0 : n;
    }
}