二分查找
我们知道二分查找的基础写法有三种:
- 左闭右闭区间
public static int binsearch(int[] nums, int target) { int l = 0, r = nums.length - 1; while (l <= r) { int m = (l + r) / 2; if (nums[m] == target) return m; if (nums[m] > target) { r = m - 1; } else { l = m + 1; } } return -1; } }
因为这是一个闭区间,l和r都能取到,当区间只有一个数的时候,如[1],l是可以等于r的,所以这里判断是l <= r。
2. 左闭右开区间
public static int binsearch(int[] nums, int target) { int l = 0, r = nums.length; while (l < r) { int m = (l + r) / 2; if (nums[m] == target) return m; if (nums[m] > target) { r = m; } else { l = m + 1; } } return -1; }
这边因为右边是开区间,r是取不到的,所以r的初始值是nums.length,而且因为r是取不到的,缩小右边区间是只需要让r = m。
3. 左开右开区间
public static int binsearch(int[] nums, int target) { int l = -1, r = nums.length; while (l < r) { int m = (l + r) / 2; if (nums[m] == target) return m; if (nums[m] > target) { r = m; } else { l = m; } } return -1; }
这里两边都是开区间,l初始值得是-1,r初始值是nums.length,同样的缩小区间是l和r直接等于m。
上面的只是基础,如果涉及到一个数组中有相同的几个值,你是无法确定选出来的目标是哪一个,如果需要找出最左边的那个位置,应该怎么写?
这里主要是要确定如果中间的值正好等于target需要怎样舍弃哪一部分。
如果要找最左边的那个值,在nums等于target是应该让r缩小。看下面例子:
可以看到最终l就停留在了最左边的3。
public static int binsearch(int[] nums, int target) { int l = 0, r = nums.length-1; while (l <= r) { int m = (l + r) / 2; if (nums[m] >= target) { r = m - 1; } else { l = m + 1; } } return l; }
相识的,如果我要得到最右边的3,我只需要改变相等情况下的区间修改。
public static int binsearch(int[] nums, int target) { int l = 0, r = nums.length-1; while (l <= r) { int m = (l + r) / 2; if (nums[m] > target) { r = m - 1; } else { l = m + 1; } } return r; }
这里返回是r。
本文作者:xiaoovo
本文链接:https://www.cnblogs.com/xiaoovo/p/17446797.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步