一维数组空间是连续的,二维地址空间是多个连续的地址空间组成。因为其连续性,导致其不能随便删除元素,只能覆盖。数组类型的题目多出二分查找,双指针,滑动窗口,模拟行为等。
1. 二分查找
1.1 思路
二分查找关键点在于对于区间的定义。主要有两种方式:左闭右闭、左闭右开。
在刷题过程中默认使用左闭右闭的方式,在这个过程中需要注意两点:
right = nums.size() - 1
if(nums[middle] > target){
right = middle - 1
}
1.2 代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, middle = 0;
int right = nums.size() - 1; //使用左闭右闭的思路
while(left <= right){
middle = left + (right - left) / 2; //这样计算中间值在索引很大的时候不容易越界
if(nums[middle] == target){
return middle;
}
else if(nums[middle] < target){
left = middle + 1;
}
else{
right = middle - 1;
}
}
return -1;
}
};
2. 数组中的移除元素
2.1 思路
因为数组中的空间中的地址是连续的,不能随便删除,所以移除元素主要是通过覆盖完成的。该题有两个解决方案:
1、使用暴力法两次循环,一次循环遍历数组,第二次循环更新覆盖数组。
2、使用双指针。慢指针和快指针同时出发,当快指针遇到需要移除的元素时,独自往前走一步。否则两者同时往前走一步,且慢指针获得快指针的元素值,这样一来,就做到慢指针不断覆盖之前数组的值。
快指针指向的是移除元素后的下一个元素
2.2 代码
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if(nums.size() <= 0){
return 0;
}
int slowIndex = 0;
for(int fastIndex = 0; fastIndex <= nums.size()-1; fastIndex++){
if(val != nums[fastIndex]){
nums[slowIndex++] = nums[fastIndex]; //原数组被不断覆盖
}
}
return slowIndex;
}
};
3. 有序数组的平方
3.1 思路
因为当数组中存在负数时,平方会变为整数,会使得乱序。
1、使用暴力解法,先平方,再排序。
2、使用双指针。数组两边数的平方一定比中间的数大,双指针指向两边,新建一个和原数组大小一样的数组,从尾端开始插入。注意最后一个元素。
3.2 代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int beginIndex = 0, endIndex = nums.size()-1;
vector<int> result(nums);
int resIndex = endIndex;
while(beginIndex <= endIndex){ //这里是为了处理最后一个元素
if(pow(nums[beginIndex],2) >= pow(nums[endIndex],2)){
result[resIndex--] = pow(nums[beginIndex],2);
beginIndex++;
}
else{
result[resIndex--] = pow(nums[endIndex],2);
endIndex--;
}
}
return result;
}
};
4. 长度最小的子数组
4.1 思路
1、使用双for循环暴力解法
2、使用滑动窗口,即双指针。快指针不断往前找大于s的数组子集,慢指针不断减小这个子集的大小
4.2 代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int resLength = INT32_MAX;
int subLength = 0;
int sum = 0;
int lowIndex = 0;
for(int fastIndex = 0; fastIndex <= nums.size()-1; fastIndex++){//快指针不断往前走找符合的子集
sum += nums[fastIndex];
while(sum >= target){
subLength = fastIndex - lowIndex + 1;
resLength = resLength < subLength ? resLength : subLength;
sum -= nums[lowIndex++];
}
}
return resLength == INT32_MAX ? 0 : resLength;
}
};
5. 螺旋数组II
5.1 思路
注意左闭右开的原则,新建一个二维n*n数组,不断往里填入数据。
5.2 代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//先建立一个二维数组
vector<vector<int>> result(n, vector<int>(n, 0));
int startx = 0, starty = 0;
int offset = 1; //因为每转一圈都需要,长度都会变短2
int loop = n/2; //转的圈数
int mid = n/2; //如果n为奇数,则需要往中间填一个数
int count = 1; //需要往数组中填入的数字
//使用左闭右开的原则
while(loop--){
int x = startx;
int y = starty;
for( ; y < starty + n - offset; y++){
result[x][y] = count++;
}
for( ; x < startx + n - offset; x++){
result[x][y] = count++;
}
for(; y > starty; y--){
result[x][y] = count++;
}
for(; x > startx; x--){
result[x][y] = count++;
}
startx++;
starty++;
offset += 2;
}
if(n%2){
result[mid][mid] = count;
}
return result;
}
};