一.数据结构:数组
文章链接:代码随想录
1.数组是存放在连续地址的相同类型数据的集合
2.二维数组也是连续地址
3.因为是连续地址,所以进行元素的增加和删除,需要对数组中的元素进行移动,保持数组地址的连续性
4.数组的删除是通过覆盖来实现的
5.可以通过下标访问数组内的元素,下标从0开始
6.要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
二.二分查找
使用前提:
1.没有重复元素
2.有序排列(使用二分查找法返回的元素下标可能不是唯一的)
循环不变量
1.边界问题:保持循环不变量,即每一次循环的时候,边界都为左闭右开,或左闭右闭
2.while(left<=right) 为左闭右闭 ,因为等于的话[5,5)没有意义,
while(left<right)为左闭右开
3.初始访问大小:左闭右闭为:0~nums.size()-1;
左闭右开为:0~nums.size();
4.二分之后的左右边界设置:保持循环不变量:即左闭右闭或左闭右开
若需要重新设置边界,说明mid不是目标值
基于这个原理,左闭右开中,若需设置右边界,则设置为mid,mid-1尚未比较,不放在开的位置。
左边界设置为mid+1;
左闭右闭中,若需设置右边界,则设置为mid-1;
左边界设置为mid+1
代码:左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();
int mid;
while(left<right)
{
mid=left + ((right - left) >> 1);
if(target>nums[mid])
{
left=mid+1;
}
else if(target<nums[mid])
{
right=mid;
}
else
{
return mid;
}
}
return -1;
}
};
小技巧:
1.利用位运算符进行除以二,使用移位操作 >>1
int middle = left + ((right - left) >> 1);
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
三.移除元素
方法:双指针法
快指针:用于搜索新元素
慢指针:用于插入符合要求的元素
代码:
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;//插入一个元素slow+1,slow即为插入元素多少
}
};
双指针皆从数组首部开始
方法:暴力求解
双循环,遇到要删除的,从后向前覆盖,数组size-1;
代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
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;
}
};
1.循环的size大小随删除元素是变化的,覆盖几个元素,最后几个元素不再遍历
2.删除后i--,再次判断,从后向前移一位那个元素是否需要删除
3.防止访问越界
for(int j=i+1;j<size;j++)
{
nums[j-1]=nums[j];
}
四.有序数组的平方
方法:双指针(初始为数组首尾两端)+一个额外数组
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left=0;
int right=nums.size()-1;
int i=nums.size()-1;
vector<int> result(nums.size());
while(left<=right)
{
if(nums[left]*nums[left]<nums[right]*nums[right])
{
result[i]=nums[right]*nums[right];
i--;
right--;
}
else
{
result[i]= nums[left]*nums[left];
i--;
left++;
}
}
return result;
}
};
1.while(left<=right) 即左闭右闭,保证循环不变量
2.插入元素,从新数组的最后一位开始