二分查找
Posted wisedu1成长之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找相关的知识,希望对你有一定的参考价值。
GitHub上有这样一个热门的开源项目,它介绍了如何刷算法,培养框架思维,这正是我正需要的。于是我把我学习过程中的笔记记录在此。原项目地址:
https://github.com/labuladong/fucking-algorithm
中国传统的元旦是指正月初一,“元旦”的概念,在不同时代、不同国家,具体所指也不尽相同。中国的“元旦”这一概念,历来指的是正月一日。“正月”的计算方法,在汉武帝时期以前也是很不统一的。因此,历代的元旦月、日也并不一致。夏时期的夏历以春季一月为正月,商时期的殷历以冬季十二月为正月,周时期的周历以冬季十一月为正月。
寻找右侧边界的二分查找
类似的,不用多言。
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
left = mid + 1;
}
}
if (right < 0 || nums[right] != target)
return -1;
return right;
}
逻辑统一
第一个,最基本的二分查找算法:
因为我们初始化 right = nums.length - 1
所以决定了我们的搜索区间是 [left, right]
所以决定了 while (left <= right)
同时也决定了 left = mid + 1 和 right = mid - 1
因为我们只需要找到一个 target 的索引即可
所以当 nums[mid] == target 时可以立即返回
第二个,寻找左侧边界的二分查找:
因为我们初始化 right = nums.length
所以决定了我们的「搜索区间」是 [left, right)
所以决定了 while (left < right)
同时也决定了 left = mid + 1 和 right = mid
因为我们需找到 target 的最左侧索引
所以当 nums[mid] == target 时不要⽴即返回
⽽要收紧右侧边界以锁定左侧边界
第三个,寻找右侧边界的二分查找:
因为我们初始化 right = nums.length
所以决定了我们的「搜索区间」是 [left, right)
所以决定了 while (left < right)
同时也决定了 left = mid + 1 和 right = mid
因为我们需找到 target 的最右侧索引
所以当 nums[mid] == target 时不要⽴即返回
⽽要收紧左侧边界以锁定右侧边界
⼜因为收紧左侧边界时必须 left = mid + 1
所以最后⽆论返回 left 还是 right,必须减⼀
根据搜索区间,全部统一成两端都闭,便于记忆,只需修改两处即可变化出三种写法:
int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = right - 1;
}
return -1;
}
int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
right = mid - 1;
}
}
if (left >= nums.length || nums[left] != target)
return -1;
return left;
}
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
left = mid + 1;
}
}
if (right < 0 || nums[right] != target)
return -1;
return right;
}
二分查找算法的细节不过如此。
以上是关于二分查找的主要内容,如果未能解决你的问题,请参考以下文章