按照方法分类
(一)二分查找
定义
思路
-
一维
- 1)设初始值:定义一个二分的开始下标为l,结束下标为r
- 2)二分一半,中间位置为 mid = l + ((r - l) >> 1), val>>1, 表示val右移一位相当于val/2,相当于 l+(r-l)/2,这样的写法是防止溢出。如果写成mid = (l+r)/2; l+r可能会溢出。- 3) 如果 tar == arr[mid],说明找到tar
- 4)比较:如果tar > arr[mid], 说明tar在区间[mid+1, r]中,l = mid + 1
- 5)如果tar < arr[mid],说明tar在区间[l, mid-1]中, r = mid - 1
- 1)设初始值:定义一个二分的开始下标为l,结束下标为r
-
二维
-
1)设初始值为右上角元素,arr[0][5] = val,目标tar = arr[3][1]
-
2)接下来进行二分操作:
- 1)如果val == target,直接返回
- 2)如果 tar > val, 说明target在更大的位置,val左边的元素显然都是 < val,间接 < tar,说明第 0 行都是无效的,所以val下移到arr[1][5]
- 3)如果 tar < val, 说明target在更小的位置,val下边的元素显然都是 > val,间接 > tar,说明第 5 列都是无效的,所以val左移到arr[0][4]
-
3)继续步骤2)
-
mid和谁比较?一般的比较原则有:
- 如果有目标值target,那么直接让arr[mid] 和 target 比较即可。
- 如果没有目标值,一般可以考虑 端点(右端点)
1、实现无重复数字的升序数组的二分查找
2、 二维数组中的查找
3、 寻找峰值
- 在这里二段性的体现是峰值的左边单调增,右边单调减。
nums[mid] < nums[mid + 1]
说明在“上坡”,则可以使left = mid + 1
(因为mid肯定不是峰值),向“峰”处压缩。- **nums[mid] > nums[mid + 1]**说明在“下坡”,则应该使
right = mid
(mid可能是峰值),往“峰”处压缩。
4、 数组中的逆序对
- 暴力法或者时归并排序法
5、 旋转数组的最小数字
- 暴力法或者是二分法:这种二分查找难就难在,arr[mid]跟谁比。
6、 比较版本号
- 双指针;版本号->数值,再进行比较;
- ‘.’前面为一组进行比较,把target 看作是右端点。
- arr[mid] > target, 说明[first … mid] 都是 >= target 的,因为原始数组是非递减,所以可以确定答案为 [mid+1…last]区间;
- arr[mid] < target, 说明答案肯定不在[mid+1…last],但是arr[mid] 有可能是答案,所以答案在[first, mid]区间arr[mid] == target:能确定答案在左边还是右边,那么就让last = last - 1