二分查找1 - leetcode35:搜索插入位置
在做lleetcode35之前,对二分查找的的算法先进行简单解释。
二分查找
基本概念
二分查找也叫作折半查找,每次查找时通过将待查找区间分成两部分并只取一部分继续查找,将查找的时间复杂度大大减小。
二分查找虽然是一种高效的查找方法,但要求数据结构具有随机访问的特点(例如数组),同时要求数据结构能够根据中间元素的特点推测两侧元素的大小关系(比如要求数组元素先排好序)。
对于一个长度为
O
(
n
)
O(n)
O(n) 的数组,二分查找的时间复杂度为
O
(
l
o
g
n
)
O(log \; n)
O(logn)。
基本算法
先设定左侧下标
l
e
f
t
left
left 和右侧下标
r
i
g
h
t
right
right,再计算中间下标
m
i
d
mid
mid;每次根据
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid] 和
t
a
r
g
e
t
target
target 的大小进行判断,相等则直接返回下标,
n
u
m
s
[
m
i
d
]
<
t
a
r
g
e
t
nums[mid] < target
nums[mid]<target 则
l
e
f
t
left
left 右移,
n
u
m
s
[
m
i
d
]
>
t
a
r
g
e
t
nums[mid] > target
nums[mid]>target 则
r
i
g
h
t
right
right 左移。
还有一些二分法的变体算法,也是基于上述变体算法进行的,这里先不进行讲述。
二分法的经典写法
需要注意以下问题:
1.循环退出条件,注意是 left <= right, 而不是 low < right;
因为很多时候 left 和 right 最后会相等
2.mid的取值,mid = left + (right - left) / 2 或者 mid = left + (right - left) >> 1
一定要注意不要写成 mid = (left + right) / 2,这样可能会溢出
题目描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为
O
(
l
o
g
n
)
O(log\;n)
O(logn) 的算法。
示例 1:
Input: nums = [1,3,5,6], target = 5
Output: 2
示例 2:
Input: nums = [1,3,5,6], target = 2
Output: 1
题解
看见题目是在排序数组中寻找是否存在一个目标值,应该立刻想到用二分法,并且此题还说明使用时间复杂度为 O ( l o g n ) O(log\;n) O(logn) 的算法,这就更明显了。
代码
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left <= right)
{
int mid = left + (right - left) / 2;
if(target == nums[mid])
{
return mid;
}
else if(target < nums[mid])
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return left;
}