二分法(LeetCode34)

二分法(LeetCode34)

  二分法强烈建议看看LC34。

  二分法(折半查找),时间复杂度O(logN)

  关于中间的取法 mid = l + (r - l) / 2;

  最好不要使用 mid = (r + l) / 2;  原因是当 l 和 r比较大的时候会超出int所能存储的值

  LC34 要找到最左边的目标值以及最右边的目标值的位置。

  可以相应的转换为找到target最左边的值,以及target+1最右边的值。

  代码可以写为:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int n = nums.length;
        if(n == 0) return new int[]{-1, -1};
        int first = findFirst(nums, target);
        if(first == n || nums[first] != target) return new int[]{-1, -1};
        int last = findFirst(nums, target + 1) - 1;
        return new int[]{first, Math.max(first, last)};
    }

    int findFirst(int[] nums, int target) {
        int l = 0;
        int r = nums.length;
        while(l < r) {
            int mid = l + (r - l) / 2;
            if(nums[mid] >= target) {
                r = mid;
            } else {
                l = mid +1;
            }
        }
        return l;
    }
}

  当然也可以分别找到最左边和最右边的值

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int n = nums.length;
        if(n == 0)  return new int[]{-1, -1};
        int l = 0;
        int r = n -1;
        int left = 0;
        int right = 0;
        //寻找最左边的target值
        while(l <= r && l < n && r >= 0) {
            int mid = l + (r - l) / 2;
            if(nums[mid] >= target) {
                r = mid -1;
            } else {
                l = mid + 1;
            }
        }
        if(l >= n|| nums[l] != target) return new int[]{-1, -1};
        left = l;
        l = 0;
        r = n - 1;
        //寻找最右边的target值
        while(l <= r && l < n && r >= 0){
           int mid = l + (r - l) / 2;
           if(nums[mid] <= target) {
               l = mid +1;
           } else {
               r = mid -1;
           }
        }
        right = r;
        return new int[]{left, right};
    }
}

  二分法最最最困难的是边界问题的考虑,所以大家对二分法的题目要有足够的耐心!

posted @ 2022-04-26 21:28  小白的学习  阅读(69)  评论(0)    收藏  举报