977. 有序数组的平方
题目链接:977. 有序数组的平方
文档讲解:代码随想录
思路
数组中的元素平方后,最大的元素始终在数组两边,因此可以考虑用相向双指针,比较两个指针的值,将较大的值赋值给结果数组的末尾。
代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int len = nums.size() - 1;
int leftIndex = 0;
int rightIndex = len;
vector<int> result(len + 1);
for (int i = 0; i <= len; i++) {
nums[i] = nums[i] * nums[i];
}
while (leftIndex <= rightIndex) {
if (nums[leftIndex] >= nums[rightIndex]) {
result[len--] = nums[leftIndex++];
}
else {
result[len--] = nums[rightIndex--];
}
}
return result;
}
};
209. 长度最小的子数组
题目链接:209. 长度最小的子数组
文档讲解:代码随想录
思路
因为以前写过,所以看到题目能够想起用滑动窗口处理,但是写代码时条件的处理不是特别熟。
根据双指针的思路,设计一个滑动窗口,使得滑动窗口内部的和始终临界满足条件,即若窗口内的值大于val,则将左指针向后移压缩窗口;若窗口内的值小于val,则将右指针向后移扩展窗口。将每次窗口的长度记录下与结果比较,返回最小的窗口长度。
代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int leftIndex = 0;
int sum = 0;
int subLen = 0;
for (int rightIndex = 0; rightIndex < nums.size(); rightIndex++) {
sum += nums[rightIndex];
while (sum >= target) {
subLen = rightIndex - leftIndex + 1;
result = result < subLen ? result : subLen;
sum -= nums[leftIndex++];
}
}
return result == INT32_MAX ? 0 : result;
}
};
相关题目
59. 螺旋数组Ⅱ
题目链接:59. 螺旋矩阵 II
文档讲解:代码随想录
思路
根据题目要求模拟螺旋这个过程,注意模拟过程中边界条件的处理以及循环不变量的确定。
代码
初始代码: 通过旋转圈数和压缩边界来完成模拟过程,模拟完后分别填补奇数边长和偶数边长的遗漏值,模拟过程不是很明确。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int top = 0, bottom = n - 1, left = 0, right = n - 1, row = 0, col = 0, s = 1;
vector<vector<int>> result(n);
for (int i = 0; i < n; i++)
result[i].resize(n);
int circle = n / 2 + 1;
for (int i = 0; i < circle; i++) {
while (col < right) {
result[row][col++] = s;
s++;
}
top++;
while (row < bottom) {
result[row++][col] = s;
s++;
}
right--;
while (col > left) {
result[row][col--] = s;
s++;
}
bottom--;
while (row > top) {
result[row--][col] = s;
s++;
}
left++;
}
if (n % 2 != 0) {
result[n / 2][n / 2] = n * n;
}
else {
result[n / 2][n / 2 - 1] = n * n;
}
return result;
}
};
代码随想录代码: 同样根据圈数模拟,但是不会压缩边界,而是确定每一圈的起始位置,根据起始位置进行每一圈的模拟。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n));
int startx = 0, starty = 0;
int i = 0, j = 0;
int loop = n / 2;
int count = 1;
for (int k = 0; k < loop; k++) {
for (i = starty; i < n - starty - 1; i++)
result[startx][i] = count++;
for (i = startx; i < n - startx - 1; i++)
result[i][n - starty - 1] = count++;
for (i = n - starty - 1; i > starty; i--)
result[n - startx - 1][i] = count++;
for (i = n - startx - 1; i > startx; i--)
result[i][starty] = count++;
startx++;
starty++;
}
if (n % 2)
result[n / 2][n / 2] = n * n;
return result;
}
};
这道题关键在于边界条件的处理,能够掌握好这道题的边界条件,就能轻松拿捏。
相关题目
总结
数组有两个基本特征:一是内存空间连续,可以实现时间复杂度O(1)的索引,但却导致增删元素的时间复杂度为O(n),同时数组的元素不能删除,只能通过后面元素将其覆盖实现;二是只能存储同一类型数据。
数组最经典的题目是二分法。二分法用于没有重复元素的有序数组,实现二分法的关键在于循环不变量的确定,在二分法中常用的处理有区间左闭右闭和左闭右开,要根据选择的循环不变量确定循环的边界条件是<
还是<=
,以及是mid + 1
还是mid
。二分法的时间复杂度是O(logn)。
双指针法也是处理数组问题的常见思路。双指针法有快慢指针型、相向双指针型以及滑动窗口等,这类问题的关键在于确定使用哪种类型的双指针、双指针的含义以及遍历哪一个指针。