数组基础
数组是存放在连续内存空间上的相同类型数据的集合。
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
所以增删数组元素时,要移动其他元素的地址 。且数组元素不是删,只能覆盖。
二维数组的地址也是连续的,数组元素地址相差的字节取决于它是什么类型的数组。
注意,严格来说vector是容器而不是数组。
704.二分查找
链接:https://leetcode.cn/problems/binary-search/description/
题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
解法一:左闭右闭
while(left---right) 里left和right使用<=,middle比较过一次,就不用包含在区间里,那么在比较middle和target时左区间或右区间就要更新为(middle+1,right)或(left,middle-1)。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right)
{
int middle=(left+right)/2;
if(nums[middle]>target)right=middle-1;//更新右区间
else if(nums[middle]<target)left=middle+1;//更新左区间
else return middle;//找到
}
return -1;//没找到
}
};
注意:定义middle时防止数据溢出 写法更正为:int middle=(left+(right-left))/2
解法二:左闭右开
和上面解法区别,left和right使用<比较。
在一开始right定义为数组长度时,左区间的右边界就已经不包括right了,所以更新时直接等于middle。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size();//注意右开right的定义
while(left<right)
{
int middle=(left+right)/2;
if(nums[middle]>target)right=middle;//更新右开区间
else if(nums[middle]<target)left=middle+1;//更新左闭区间
else return middle;
}
return -1;
}
};
注意,定义middle时防止数据溢出 写法更正为:
int middle = left + ((right - left) >> 1);
27.移除数组
题目:https://leetcode.cn/problems/remove-element/description/
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
暴力解法
比较简单,就是找到要移除的数,并把后面的数一个个向前覆盖。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len=nums.size();
for(int i=0;i<len;i++)
{
if(nums[i]==val)
{
for(int j=i+1;j<len;j++)
nums[j-1]=nums[j];
i--;
len--;//好理解,就是覆盖
}
}
return len;
}
};
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
快慢指针法
图示理解:
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
我的理解是:快慢指针一起遍历数组,但是当快指针遇到目标元素时,慢指针保持不动,即快指针所指元素不赋值给它,慢指针得到新的数组下标位置。注意:该过程中元素的相对位置没有改变。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex=0;
for(int fastindex=0;fastindex<nums.size();fastindex++)
{
if(val!=nums[fastindex])//没有找到删除元素则正常赋值,和快指针一并移动
{
nums[slowindex]=nums[fastindex];
slowindex++;
}
}
return slowindex;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
977.有序数组的平方
题目:977. 有序数组的平方 - 力扣(LeetCode)
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
- 输入:nums = [-4,-1,0,3,10]
- 输出:[0,1,9,16,100]
- 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
示例 2:
- 输入:nums = [-7,-3,2,3,11]
- 输出:[4,9,9,49,121]
双指针法
图示理解:
思路,原有数组定义两个指针i和j,i指向数组起始位置,j指向数组末位。
定义一个新数组来存储平方且排序后的原数组元素,并由指针k指向末尾
比较i和j指向元素的平方,较大者赋值给新数组(从末位开始),并更新i,j,k的指向。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int a=nums.size()-1;
vector<int>result(a+1,0);
for(int i=0,j=a;i<=j;)
{
if(nums[i]*nums[i]>nums[j]*nums[j])
{ result[a]=nums[i]*nums[i];
a--;
i++;
}
else
{ result[a]=nums[j]*nums[j];
a--;
j--;
}
}
return result;
}
};
暴力解法:每个数平方后,用sort函数排序。