一、704. 二分查找
题目链接:力扣
1.1 题目的第一想法
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size(),mid;
while(left<=right) {
mid=(right+left)/2;
if(nums[mid]==target)
return mid;
else if(nums[mid]>target) {
right=mid;
}
else{
left=mid;
}
}
return -1;
}
};
结果:通过测试用例:6 / 47。
1.2
看完代码随想录之后的想法
自己的想法跟接近左闭右开的区间里,也就是[left, right),但是while循环的条件和左边界left的更新错误。
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
文章讲解:代码随想录
1.3
今日收获和学习时长
知道了二分法的两种思路:
1)第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)。
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下三点:
1. while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
2. if (nums[middle] > target) right 要赋值为 middle - 1 ,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1 !!
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下三点:
1. while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
2. if (nums[middle] > target) right 要赋值为 middle - 1 ,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1 !!
3.
if (nums[middle] < target) left 要赋值为 middle + 1
!!
2)二分法第二种写法
如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。
有如下两点:
while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]。
如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。
有如下两点:
while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]。
3)学习时长45min。
二、27. 移除元素
题目链接:力扣
2.1 题目的第一想法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
sort(nums.begin(),nums.end());
int ans=nums.size();
for(int i=0;i<ans;i++)
{
if(nums[i]==val)
{
int temp=nums[ans-1];
nums[ans-1]=nums[i];
nums[i]=temp;
ans--;
}
}
return ans;
}
};
结果:通过测试用例:91/ 113。因为ans和ans-1变化了,导致遍历不完整。
2.2
看完代码随想录之后的想法
文章讲解:代码随想录
1)先试试暴力的双for循环
开始没理解i--的含义,其实就是i的值变了,需要重新判断。
同时,在自已的方法的if条件句中加入i--,也能通过全部样例。
2)双指针法
fast遍历原数组,slow保存需要的值、再++,最后slow的大小也就是新数组的大小。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int i=0,j=0;
for(;i<nums.size();i++)
{
if(nums[i]!=val)
{
nums[j]=nums[i];
j++;
}
}
return j;
}
};
2.3
今日收获和学习时长
接触过类似的题目,就是在原数组上实现覆盖操作。
时长1h。