二分查找的难点在于,确定查找的区间。
我到底是在[left,right]中查找,还是在[left,right)中查找呢?
while循环中的条件到底是left<=right呢,还是left<right.
class Solution {
public int search(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length - 1;
int mid;
while (left <= right) {
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;
}
}
今天搞明白了!
二分查找的用法有两种。
第一种是在[left,right]也就是左闭右闭区间中查找。(上边代码演示的那种)个人喜欢使用,因为不容易乱
在这种情况下,left=right是有意义的。因此,我们就需要把while循环里边的条件设置成left<=right.
相应地,因为left=right有意义,所以mid有取到left和right的可能。所以查找区间更新时需要将mid设置为left = mid+1或right=mid-1。
第二种是在[left,right)也就是左闭右开区间中查找。
在这种情况下,left=right是没有意义的,因为区间取不到right。所以,我们需要把while循环里边的条件设置为left<right.
相应地,因为left不会等于right,所以mid永远取不到right。所以查找区间更新时需要将mid设置为left=mid或right=mid。
比如,当前数组arr[mid]等于target时,直接返回mid。
当前数组arr[mid]<target时,表明需要去[left,right)的右半部分查找,那么就需要把左指针left往右移动。又因为查找区间是左闭右开的,left是可以取到的。mid这个位置已经验证过arr[mid]<target,所以mid这个位置没有再查的必要。所以把left=mid+1。
当前数组arr[mid]>target时,表明需要去[left,right)的左半部分查找,那么需要把右指针right向左移动。又因为查找区间是左闭右开的,right是取不到的。 所以就可以让right=mid,因为right这个位置在查找时是取不到的,所以mid这个位置也是娶不到的。
有点乱,全当自己捋一下思路。