二分查找
题目类型:
在【有序】且【无重复元素】的数组中,找到target元素下标
思路:
一分为二,middle>target,区间右边缩小;middle<target,区间左边变大
注意点:
- 两个int相加可能会越界
- 根据区间定义决定right/left写法,middl小于target时候,两种方法left更新都是middle+1
-
左闭右闭[left,right] , left=right是合法的->while(left<=right),** right减,大的减,小的加 **
int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right] while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <= int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2 if (nums[middle] > target) { right = middle - 1; // target 在左区间,所以[left, middle - 1] } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,所以[middle + 1, right] } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } ```
-
左闭右开[left,right) ,** right不变,大不变,小的加**
int right = nums.size(); while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 < int middle = left + ((right - left) >> 1); if (nums[middle] > target) { right = middle; // target 在左区间,在[left, middle)中 } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,在[middle + 1, right)中 } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } ```
-
代码示例
C++
class Solution {
public:
int search(vector<int>& nums, int target) {
int left =0;
int right = nums.size()-1;
while(left<=right){
int middle=left+((right-left)/2);
if(nums[middle]>target){
right=middle-1;
}
else if(nums[middle]<target){
left=middle+1;
}
else{
return middle;
}
}
return -1;
}
};
python
class Solution:
def search(self, nums: List[int], target: int) -> int:
left=0
right=len(nums)-1
while left<=right:
middle=left+(right-left)//2
if nums[middle] > target:
right=middle-1
elif nums[middle] < target:
left=middle+1
else:
return middle
return -1
移除元素
题目类型
给数组,给目标值,删除目标值,返回新数组的长度
思路
- 库函数 erase() 时间复杂度O(n)
- 双循环
- 双指针:快慢指针,快指针指向新数据所需元素,新数组下标是slow指针 ,相当于** 把不是target的元素全部提出到另一个数组nums[slow]中**
这题解法的核心就是遍历数据过程中遇到等于目标值就直接跳过,不等于目标值就赋值,这样就能 过滤掉(也就是删除掉)目标值
注意点
慢指针使用了要+1
代码示例
双指针重建新数组nums[slow],把不是target的都放到新数组中
C++写法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow =0;
for(int fast =0;fast<nums.size();fast++){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
};
python 写法
def removeElement(self, nums: List[int], val: int) -> int:
fast=0
slow=0
size=len(nums)
for fast in range(size):
if nums[fast]!=val:
nums[slow]=nums[fast]
slow+=1
return slow
收获总结
双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法
有环:快慢指针定会相遇