一.数组理论基础
文章链接:[https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html](https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html)
简单复习一下上学期学的数组内容
##### 704. 二分查找(之前写过一遍,当巩固提高)
题目链接:[https://leetcode.cn/problems/binary-search/](https://leetcode.cn/problems/binary-search/)
文章讲解:[https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html](https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html)
状态:做出来巩固提高
1.前提条件:
(1)**数组为有序数组**(看到这个想想二分)
(2)**数组中无重复元素**(否则下标不唯一)
2.vector容器;
(1)创建:vector<int> nums;
(2)获取长度:nums.size( );
3.两种写法(数学中区间的定义,while每次要保证不变量,即循环不变量原则)
(1)**左闭右闭**([left,right])(本人常用)
因为left可以等于right,所以while(left<=right);
且if(nums[mid])>target{right=mid-1;}
(2)**左闭右开**([left,right])
因为left小于right,所以while(left<right);
且if(nums[mid])>target{right=mid;}
4.我的代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int lef=0;
int rig=nums.size()-1;
while(lef<=rig){
int mid=(lef+rig)/2;
if(nums[mid]==target){
return mid;
}
else if(nums[mid]<target){
lef=mid+1;
}
else{
mid=lef-1;
}
}
return -1;
}
};
4.二分本质:
**根据是否满足题目的条件来缩小答案所在的区间**(题目变种改变if的条件)
5.注意
(1)优势:时间复杂度O(logn)
(2)关于二分mid溢出问题解答:
mid = (l + r) / 2时,如果l + r 大于 INT_MAX(C++内,就是int整型的上限),那么就会产生溢出问题(int类型无法表示该数)
所以写成 mid = l + (r - l) / 2或者 mid = l + ((r - l) >> 1) 可以避免溢出问题(右移比除法快)
6.补充题:35.搜索插入位置 和 34. 在排序数组中查找元素的第一个和最后一个位置(今天在敲小学期上的c++类的作业和加上自己对二分法比较熟就暂时不写,之后找时间补上)
##### 27. 移除元素
题目链接:[https://leetcode.cn/problems/remove-element/](https://leetcode.cn/problems/remove-element/)
文章讲解:[https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html](https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html)
状态:暴力解决,学习双指针
1.暴力法(知道是两层循环后一个元素覆盖前一个元素,但担心O(n^2)的时间复杂度过不了,用了vector的erase函数讨了个巧,正好再回顾一下vector)
代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k=nums.size();
for(auto it=nums.begin();it!=nums.end();){
if(*it==val){
it=nums.erase(it);
k--;
}
else{
it++;
}
}
return k;
}
};
2.vector容器:
(1)迭代器:vector<int>::iterator it或auto it
(2)erase函数(**注意**,一开始没理解写错了)
erase函数可以用于删除vector容器中的一个或者一段元素,在删除一个元素的时候,其参数为指向相应元素的迭代器,而在删除一段元素的时候,参数为指向一段元素的开头的迭代器以及指向结尾元素的下一个元素的迭代器;
在进行单个元素删除后,传入的迭代器指向不变,仍然指向被删除元素的位置,而被删除元素之后的所有元素都向前移动一位,也就是该迭代器实际上是指向了原来被删除元素的下一个元素。
删除一段元素后,传入的迭代器指向也是不变的,仍然指向原来传进去时候的位置,修改的是删除段后面的元素的位置。
样例:
for(auto iter=vec.begin();iter!=vec.end(); )
{
if( *iter == 3)
iter = veci.erase(iter);//当删除时erase函数自动指向下一个位置,就不需要进行++,否则会超过.end( )
else
iter ++ ; //当没有进行删除的时候,迭代器++
}
3.双指针法(**重点**)(不改变元素顺序)
双指针法(快慢指针法): **通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。**(时间复杂度变为O(n))
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新的新数组下标的位置
代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex=0;
for(int fastindex=0;fastindex<nums.size();fastindex++){
if(nums[fastindex]!=val){
nums[slowindex]=nums[fastindex];
slowindex++;
}
}
return slowindex;
}
};
4.补充题:
√26.删除排序数组中的重复项 https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
今日解决:力扣打开缓慢问题
待解决:Dev-c++怎么调试类?以及VS登不上力扣刷题。
坚持第一天,明天继续!