二分查找

5 阅读2分钟

二分查找

  1. 数组必须是有顺序的。
  2. 如果遍历结束,left>=right;
  3. 可以获取最左侧的数和最右侧的数。

正常程序

每个表变量都要有定义,这里面的[left,right],这里是闭区间。

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

leetcode_33 搜索旋转排序数组

将升序的数组nums,在第k位进行旋转。k,k+1...0,1,2...搜索数组中的值。 思路:二分查找要在有顺序中查找,要保证一侧是有序的。如果不在有序的一侧,就在另一侧

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;
        }
        if (nums[left] <= nums[mid]) {
            if (target >= nums[left] && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (target <= nums[right] && target > nums[mid]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return -1;
}

leetcode_81 搜索旋转排序数组

这个和上面的那个差不多,这是这里面有重复元素。当left,mid,right都相等时,这种情况需要特殊处理。例如[4,4,4,4,1,2,3,4,4,4,4,4,4,4,4]。left,mid,right的值都是4,所以需要将这个情况特殊处理。

public boolean search(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            return true;
        }
        if (nums[left] == nums[mid] && nums[mid] == nums[right]) {
            left++;
            right--;
            continue;
        }
        if (nums[left] <= nums[mid]) {
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid -1;
            }
        }
    }
    return false;
}

leetcode_34 在排序的数组中查找元素的第一个和最后一个位置

找到目标值的第一个和最后一个位置。正常的二分查找在找到元素后就返回。找最左侧的位置,要将while(left<=writh)循环完。在nums[mid]==target时,也要将right=mid-1;并将此时的mid进行记录。right=mid-1,有可能会比targe小,但是在等于时已经进行了记录。

public int[] searchRange(int[] nums, int target) {
    int[] arr = new int[2];
    arr[0] = searchLeftIndex(nums, target);
    arr[1] = searchRightIndex(nums, target);
    return arr;
}

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

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