704.二分查找
题目链接:704.二分查找
使用二分法的常见前提条件:1、 有序数组 2、数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的
二分查找一般分为“左闭右闭”和“左闭右开”两种常见情况,所谓“开”“闭”指的是数组的左右边界是否在区间内,这关系到右端点right的值,while循环以及if的判断:以前者为例,当左右都为闭区间时,右端点包含在查找内部,因此right = nums.size()-1;数组的下标可以使left=right,因为此时左右端点都在数组的内部,因此判断条件为while(left <= right);同理,如果左右端点可以相等,那么此时target的大小判断之后应该使left = middle+1或right = middle-1把已经判断完成的部分排除在下一次判断之外
还有需要注意的一点是,int mid = left + (right - left) / 2来确认数组的中间点而不是(right + left) / 2的原因是防止当left和right都很大的时候两者相加导致整数溢出的情况,(right - left) / 2表示的是左端点到右端点之间的距离的一半
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 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
{
return mid;
}
}
return -1;
}
};
27. 移除元素
题目链接:27. 移除元素
移除数组元素的难点在于“原地”删除并且修改数组,这意味着使用数组后续的数据对所需要移除的数据进行覆盖从而修改数组的长度
除了使用暴力法——两个for循环对数组进行遍历与全体更新以外,还可以使用双指针fast和slow法,fast指向每一个元素并在循环中遍历数组以找到需要移除的元素,slow指向更新之后的数组,实际上就是把一个数组当成两个数组来用,slow指向的数组相当于一个新创建的数组,只不过在没有遇到第一个要删除的元素之前fast和slow指向的是同一个东西,找到第一个之后slow使用的数据fast将不再使用,也就相当于一个新的数组的出现
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;
}
};
相较于暴力法,双指针的时间复杂度为一个for循环的O(n)