二分
二分可以看做优化版的枚举
二分简介
- 二分法是一种在有序数组中查找特定元素的高效算法。它通过将查找范围一分为二,然后根据中间元素与目标元素的比较结果,决定继续在左半部分还是右半部分查找,从而逐步缩小查找范围,直到找到目标元素或确定目标元素不存在。
二分的特点
- 可以进行查找
- 速度快,效率高
- 可以用于任何数组
- 实现简单
二分的原理
- 二分法是利用了二段性,将区间一分为二,然后判断答案在左区间还是右区间,然后递归处理。
- 二分法一般用于求解单调函数的最值问题,即求函数的最大值或最小值。
- 二分法的时间复杂度是O(logn),其中n是区间的长度。
二分法的关键在于确定每次二分后,答案在左区间还是右区间,然后递归处理。
二分的流程
- 确定二分区间,一般是一个有序的区间。
- 确定二分条件,即如何判断答案在左区间还是右区间。
- 确定二分终止条件,即如何判断二分已经找到答案。
- 确定二分更新方式,即如何更新二分区间。
二分与枚举的区别
| 枚举 | 二分 | |
|---|---|---|
| 时间复杂度 | O(n) | O(logn) |
| 空间复杂度 | O(1) | O(1) |
| 适用范围 | 任何数组 | 单调函数 |
| 实现难度 | 简单 | 相对枚举稍难 |
二分模板
- 二分模板
C++
int l = 0, r = n - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
}
Python
l = 0
r = n - 1
while l < r:
mid = (l + r) >> 1
if check(mid):
二分查找
- 二分查找是一种在有序数组中查找特定元素的算法。它通过将查找区间一分为二,然后根据比较结果决定在左半部分还是右半部分继续查找,从而逐步缩小查找范围,直到找到目标元素或确定目标元素不存在。
- 二分查找的时间复杂度为O(logn),其中n是数组的长度。这是因为它每次都将查找区间缩小一半,因此查找次数最多为logn次。
- 二分查找的算法流程如下:
- 初始化左边界l为0,右边界r为数组长度减1。
- 当l小于r时,执行以下步骤:
- 计算中间位置mid,即mid = (l + r) // 2。
- 比较目标元素target与数组中mid位置的元素:
- 如果target等于数组中mid位置的元素,则返回mid。
- 如果target小于数组中mid位置的元素,则将右边界r更新为mid - 1。
- 如果target大于数组中mid位置的元素,则将左边界l更新为mid + 1。
- 如果循环结束后仍未找到目标元素,则返回-1,表示目标元素不存在于数组中。
- 二分查找的算法实现如下:
C/C++
int binarySearch(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while (l < r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return -1;
}
Python3
def binary_search(nums, target):
l, r = 0, len(nums) - 1
while l < r:
mid = (l + r) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
l = mid + 1
else:
r = mid - 1
return -1
Java
public int binarySearch(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return -1;
}
JavaScript
function binarySearch(nums, target) {
let l = 0, r = nums.length - 1;
while (l < r) {
const mid = Math.floor((l + r) / 2);
if (nums[mid] === target) {
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return -1;
}
Go
func binarySearch(nums []int, target int) int {
l, r := 0, len(nums)-1
for l < r {
mid := (l + r) / 2
if nums[mid] == target {
return mid
} else if nums[mid] < target {
l = mid + 1
} else {
r = mid - 1
}
}
return -1
}
TypeScript
function binarySearch(nums: number[], target: number): number {
let l = 0, r = nums.length - 1;
while (l < r) {
const mid = Math.floor((l + r) / 2);
if (nums[mid] === target) {
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return -1;
}
PHP
function binarySearch($nums, $target) {
$l = 0;
$r = count($nums) - 1;
while ($l < $r) {
$mid = floor(($l + $r) / 2);
if ($nums[$mid] === $target) {
return $mid;
} elseif ($nums[$mid] < $target) {
$l = $mid + 1;
} else {
$r = $mid - 1;
}
}
return -1;
}
Ruby
def binary_search(nums, target)
l, r = 0, nums.length - 1
while l < r
mid = (l + r) / 2
if nums[mid] == target
return mid
elsif nums[mid] < target
l = mid + 1
else
r = mid - 1
end
end
-1
end
Rust
fn binary_search(nums: Vec<i32>, target: i32) -> i32 {
let mut l = 0;
let mut r = nums.len() - 1;
while l < r {
let mid = (l + r) / 2;
if nums[mid] == target {
return mid as i32;
} else if nums[mid] < target {
l = mid + 1;
} else {
r = mid - 1;
}
}
-1
}
C#
public int BinarySearch(int[] nums, int target)
{
int l = 0;
int r = nums.Length - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (nums[mid] == target)
{
return mid;
}
else if (nums[mid] < target)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return -1;
}
433

被折叠的 条评论
为什么被折叠?



