二分法代码笔记
最近复习二分法的题目,发现左右区间的二分写法总是无法第一时间写出正确的,故痛定思痛,通过写笔记的形式记录下来。
这里需要说明的是,二分法多用于单调情况下的LogN复杂度的搜索,并非只用于排序数组。二分法是一种高效的搜索方法,前提是能分析出问题是随某一个自变量的单调函数
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 From: https://www.cnblogs.com/jentreywang/p/16599780.html