ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

二分法代码笔记

2022-08-18 19:00:42  阅读:105  来源: 互联网

标签:right target nums int 代码 mid 笔记 二分法 left


二分法代码笔记

最近复习二分法的题目,发现左右区间的二分写法总是无法第一时间写出正确的,故痛定思痛,通过写笔记的形式记录下来。

这里需要说明的是,二分法多用于单调情况下的LogN复杂度的搜索,并非只用于排序数组。二分法是一种高效的搜索方法,前提是能分析出问题是随某一个自变量的单调函数

参考 labuladong - 二分查找

PS: 十分感谢 labuladong的微信文章,学习算法分门别类很重要!

0 入参

int[] nums, int target

1 找一个数

  • 搜索区间
    • 根据 left 和 right 的定义,可知搜索区间为 [left, right]
  • 停止条件为
    • 找到了: return mid;
    • 没找到: when left = right + 1, return -1;
  • 左右子搜索区间分别为(此时 nums[mid] != target)
    • 左 [left, mid - 1]
    • 右 [mid + 1, right]
int left = 0;
int right = nums.length - 1;
while (left <= right) {
    int mid = left + (right - left) / 2;
    int midVal = nums[mid];
    if (midVal == target) {
        return mid;
    } else if (midVal < target) {
        right = mid - 1;
    } else {
        left = mid + 1;
    }
}
return -1;

2 找左侧边界

小提醒,查找左右边界,都是要检查最后查找的元素 nums[i] == target

如果不等于,则数组中没有 target 元素

  • 定义
    • 返回有序数组中,小于 target 值的元素的个数
    • 或者,第一个等于target 的下标
    • 返回值 i 的取值, nums[i] >= target
  • 返回值的取值范围是 [0,nums.length]
    • 讨论越界下标的情况 nums.length
    • 当 left = right = nums.length时
    • 不会进入while,直接返回 left = right = nums.length
    • 所以不存在越界问题
  • 核心思想
    • 搜索区间[left, right)向左收缩
    • 检测完 nums[mid]之后,应当去掉mid,将区间划分为:
      • [left, mid)
      • [mid + 1, right)
  • 搜索区间
    • 根据 left 和 right 的定义,可知搜索区间为 [left, right)
  • 终止条件
    • left = right ,此时返回 left 和 right 都可以
int left = 0;
int right = nums.length;
while (left < right) {
    int mid = left +  (riht - left) / 2;
    int midVal = nums[mid];
    if (midVal == target) {
        right = mid;
    } else if (midVal < target) {
        left = mid + 1;
    } else {
        right = mid;
    }
}
return left;

3 找右侧边界

与左侧边界相似

  • 定义
    • 返回有序数组中,<= target 值的元素的下标
    • 或者,最后一个等于target 的下标
    • 返回值 i 的取值, nums[i] <= target
  • 返回值的取值范围是 [0,nums.length]
    • 讨论越界下标的情况 nums.length
    • 当left = right = nums.length 时
    • 不会进入while,直接返回 left = right = nums.length
    • 所以不存在越界问题
  • 核心思想
    • 搜索区间[left, right)向右收缩
    • 检测完 nums[mid]之后,应当去掉mid,将区间划分为:
      • [left, mid)
      • [mid + 1, right)
int left = 0;
int right = nums.length;
while (left < right) {
    int mid = left + (right - left) / 2;
    int midVal = nums[mid];
    if (midVal == target) {
        left = mid + 1;
    } else if (midVal < target) {
        left = mid + 1;
    } else {
        right = mid;
    }
}
return left - 1;

单独讨论 return left - 1 这条语句,由于最终的最终,left = right = mid + 1;

此时,可知nums[mid] <= target

由于 left = right = mid + 1

可以推测 nums[left] >= target

存在大于的风险,因此返回 mid 就行了,

由于可能存在不进入循环,mid是while中的局部变量

因此返回 left - 1 或者 right - 1 就行了,越界章节开头已经讨论过。

标签:right,target,nums,int,代码,mid,笔记,二分法,left
来源: https://www.cnblogs.com/jentreywang/p/16599780.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有