二分查找思路以及可能出现情况对应解决办法
  TEZNKK3IfmPf 2023年11月14日 28 0

二分查找又叫折半查找,但是很容易写错,因为不好界定边界

首先看一道二分查找的题目
 135. 搜索插入位置
2给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
3
4你可以假设数组中无重复元素。
5
6示例 1:
7
8输入: [1,3,5,6], 5
9输出: 2
10示例 2:
11
12输入: [1,3,5,6], 2
13输出: 1
14示例 3:
15
16输入: [1,3,5,6], 7
17输出: 4
18示例 4:
19
20输入: [1,3,5,6], 0
21输出: 0
分析

二分查找基础条件是建立在有序数组的基础上,本题就是有序数组,然后目标数字与数组中各个值进行比较,

  1. 目标值比第一位元素小
  2. 目标值比最后一位元素大
  3. 目标值介乎于前俩种情况之间
解法1 暴力

从第一位遍历与目标值比较,确定位置,此处只说明思路,时间复杂度 o(n)

解法2 二分查找

首先说明一下题目中说数组无重复数据,所以暂且不考虑重复情况,重复情况在文末进行说明
首先确定题中的不变量[left,right],既[0,nums.length-1],左闭右闭区间
看一下我的写法

 1  /**
2     * 二分法 首先确定不变量,既不变区间【0,nums.length -1】,左闭右闭区间
3     * @param nums
4     * @param target
5     * @return
6     */

7    public int searchInsert(int[] nums, int target) {
8        int left = 0;
9        int right = nums.length -1;
10        while(left <= right){
11           //避免溢出
12            int middle  = left + ((right -left)/2);
13            if(nums[middle]<target){
14                left = middle + 1;
15            }else if(nums[middle]>target){
16                right = middle -1;
17            }else{
18                return middle;
19            }
20        }
21        return right+1;
22    }

小结
以上题目主要想说明二分前确定好区间,才能确定好边界条件

二分查找重复值问题

当我们遇到[1,2,2,2,2,2]或者[1,1,1,2]这种情况可能会出现死循环该如何解决。
其实这种情况只会出现在二分查找的第三个判断上,既
nums[middle] == target

所以只需要对这块进行处理,既向左以及想有找到所有相同元素的下标,至于要取最左还是最右看你的需求,那么看一下代码

 1else {    //表示arr[mid] == val
2                /*思路分析
3                1.在找到mid索引值,不要马上返回
4                2.向mid索引值的左边扫描,将所有满足1000,的元素的下标, 加入到集合ArrayList
5                3.向mid索引值的右边扫描,将所有满足1000, 的元素的下标,加入到集合ArrayList
6                4.将ArrayList返回*/

7
8                //向mid左边扫描
9                int temp = mid - 1;
10                while (true) {
11                    if (temp < 0 || arr[temp] != val)//没有找到就退出循环
12                        break;
13                    //执行到这里说明找到了,就把找到的元素添加到集合中,继续向左找
14                    indexList.add(temp);
15                    temp -= 1;
16                }
17                indexList.add(mid);//加入已经找到了的元素【arr[mid]==val】
18                //向mid右边扫描
19                temp = mid + 1;
20                while (true) {
21                    if (temp > arr.length - 1 || arr[temp] != val)
22                        break;
23                    //执行到这里说明找到了,就把找到的元素添加到集合中,继续向右
24                    indexList.add(temp);
25                    temp += 1;
26                }
27                return indexList;
28            }

测试用例 :int[] arr = {1, 2, 3, 5, 6, 6,6, 6, 7, 8, 9};
target = 6;
返回的 indexList 就是 [4,5,6,7]既为数组中为6的下标;

总结

二分查找

  1. 注意边界条件
  2. 注意为有序数组
  3. 注意数组是否有重复元素
    确定以上问题之后二分问题就能迎刃而解了
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月14日 0

暂无评论

TEZNKK3IfmPf