Day1 | 704.二分查找、27.移除元素
704.二分查找 题目链接
初见思路:用mid对应的值与target是否相等来控制循环
结果超时。
伪代码如下:(仅为个人记录思考过程)
int left=0;
int right=nums.size()-1;
int mid=(left+right)/2;
while(target!=nums[mid]){
if(right-1==left)
return -1;
if(target<nums[mid]){
right=mid-1;
mid=(left+right)/2;
}
else if(target>nums[mid]){
left=mid+1;
mid=(left+right)/2;
}
}
return mid;
看了讲解之后明白 使用二分法时,首先就要明确区间范围,由于整数型在除法时直接舍去小数部分,不同的区间在循环判断是截然不同。
改进后:
首先根据区间情况,确定while中判断条件 left< or <= right。
再确定left和right 后续变化 是=mid 还是=mid± 1
左闭右闭:
当left<=right时,仍合法,所以需要等号。
比较判断后,端点值一定不是target值,但仍是合法区间(由于是闭区间),所以我们需要手动加减1。
伪代码如下:
int left=0;
int right=nums.size()-1;
int mid=(left+right)/2;
while(target!=nums[mid]){
if(right-1==left)
return -1;
if(target<nums[mid]){
right=mid-1;
mid=(left+right)/2;
}
else if(target>nums[mid]){
left=mid+1;
mid=(left+right)/2;
}
}
return mid;
左闭右开:
当left=right时,不合法,所以不需要等号。
所以在开始left赋值时,直接等于nums.size()。
即left<right.
接下来判断后,left同上,需要加1,right本身端点值一定不是target值,已经由区间排除在外。所以不需要我们手动减1,就直接变为mid即可。
27.移除元素 题目链接
tips:数组无法删除,只能覆盖
vector.erase()也是覆盖 复杂度为O(n).
初见思路:for循环暴力求解
值得注意的是:这里不能直接用nums.size() 作为循环范围,因为他不变。
int size=nums.size();
for(int i=0;i<size;i++){
if(nums[i]==val){
for(int j=i+1;j<size;j++){
nums[j-1]=nums[j];
}
i--;
size--;
}
}
return size;
改善后:使用快慢指针
只需要一层for循环,原理如下:
快指针 遍历数组寻找需要的元素(删除之后剩下的元素)
慢指针 给寻找到的元素赋下标
int slow=0;
for(int fast=0;fast<nums.size();fast++){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
}
return slow;