算法训练营第一天| 704. 二分查找、27. 移除元素

349 阅读1分钟

LeetCode 704. Binary Search

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] == target){
                return mid;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
        return -1;
    }
}

有序数组查找问题,优先想到二分查找。

搜索一个元素时,搜索区间两端闭(左闭右闭),初始化为int left = 0, right = nums.length - 1,while条件带等号(<=),if相等就返回,更新时在mid基础上必须加减1,while结束后return -1;

搜索左右边界时,左闭右开(最常用),初始化为int left = 0, right = nums.length;,while要用小于号(<),if相等别返回,利用mid锁边界,更新时在mid基础上是left = mid + 1right = mid, while结束(left == right)后,搜索左侧边界返回return left;,搜索右侧边界返回return left - 1;(right - 1 也是一样的)。

参考资料:labuladong的算法小抄

拓展题

34. Find First and Last Position of Element in Sorted Array

class Solution {
    public int[] searchRange(int[] nums, int target) {
        return new int[]{searchLeft(nums, target), searchRight(nums,target)};
    }
    private int searchLeft(int[] nums, int target){ // 搜索左侧边界
        int left = 0, right = nums.length - 1;
        // 搜索区间[left, right]
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
                left = mid + 1;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
            else if(nums[mid] == target){ // 收缩右侧边界
                right = mid - 1;
            }

        }
        // 检查出界情况
        if(left >= nums.length || nums[left] != target){
            return -1;
        }
        return left;
    }

    private int searchRight(int[] nums, int target){ // 同样道理搜索右侧边界
        int left = 0, right = nums.length - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if (nums[mid] < target){
                left = mid + 1;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
            else if(nums[mid] == target){
                left = mid + 1;
            }
        }

        if(right < 0 || nums[right] != target){
            return -1;
        }
        return right;
    }
}

35. Search Insert Position

class Solution {
    public int searchInsert(int[] nums, int target) {
        /**
        二分搜索的目标是寻找第一个不小于 target 的元素的位置。
        如果 target 大于数组中所有的元素,那么应该返回的位置就是数组的长度,也就是 nums.length。
        因此,我们需要将搜索的范围设置为 [0, nums.length]。
        */
        int left = 0, right = nums.length;
        while(left < right){
            int mid = left + (right - left) / 2;
            if(nums[mid] == target){
                right = mid;
            }
            else if(nums[mid] < target){
                left = mid + 1;
            }
            else{
                right = mid;
            }
        }

        return left;
    }
}

LeetCode 27. Remove Element

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0, fast = 0;

        // 以下处理完后,所有nums中不等于val的元素都在nums的开头slow个位置,slow的大小即为这个nums中不等于val的元素的个数
        while(fast < nums.length){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            }
            fast++; // 当fast所指位置nums[fast]等于val时则只有fast++
        }
        
        return slow;
    }
}

由于题目要求原地修改数组,所以用双指针,想到这个方法之后就比较简单了。