代码随想录算法训练营第一天 | 704. Binary Search | 27. Remove Element

55 阅读2分钟

leetcode.com/problems/bi…

思路:因为数组是升序排列的,那么可以通过二分来以O(logN)的复杂度查找target,如果遍历每一个数的话,那就是O(N)了。那么二分的话,首先就是要明确对区间的定义是左闭右闭的区间,还是左闭右开的区间。然后两个int想加,可能越界,最好处理一下,注意题目的数据范围。然后就是除法操作可以用移位运算符代替。进入循环之后,更新区间的时候是直接等于middle还是middle-1?因为区间是左闭右闭的,所以应该是middle-1,不然就重复判断之前的数了。还有就是这道题好像很多同学容易TLE,应该是因为mid更新放到了循环外面吧

class Solution {
    public int search(int[] nums, int target) {
        // int mid = nums.length / 2;
        // while (mid >= 0 && mid <= nums.length - 1) {
        //     if (nums[mid] == target) {
        //         return mid;
        //     }
        //     if (nums[mid] < target) {
        //         mid = (mid + nums.length - 1) / 2;
        //     }
        //     if (nums[mid] > target) {
        //         mid = mid / 2;
        //     }
        // }
        // return -1;
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] > target) {
                // 不包含mid 因为已经判断过了
                right = mid - 1;
            }  else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

leetcode.com/problems/re… 27. 移除元素

思路:暴力解法就是两个for循环,时间复杂度O(n^2)。这道题目用双指针显然会好很多,因为可以只用遍历一遍数组,复杂度O(N^2)。那么双指针做法就是定义两个指针,一个快一个慢,都从0开始,快指针用来找新数组也就是移除元素之后的数组中的值,而慢指针就是新数组的下标。

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        int fast = 0;
        // 快慢指针同步走
        while (fast < nums.length) {
            // 如果找到目标元素,快指针移动到后面一个,然后交换快慢指针的值,覆盖掉目标元素
            if (nums[fast] != val) {
                // 把需要的元素复制给新数组下标
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;
    }
}

总结:实际上二分并不是数组有序的情况下才能使用,有一些局部升序降序,但是总体可能无序的数组也是可以用到二分的,这个以后碰到对应题目再聊。