977.有序数组的平方
使用双指针法解题。
为什么能想到用双指针呢?因为有序数组的平方不一定是有序数组,但是最大值一定是从两边向中间递减。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size() - 1;
vector<int> result(n + 1);
for (int i = 0, j = n; i <= j;) {
if (nums[i] * nums[i] <= nums[j] * nums[j]) {
result[n--] = nums[j] * nums[j];
--j;
}
else {
result[n--] = nums[i] * nums[i];
++i;
}
}
return result;
}
};
209.长度最小的子数组
暴力解法
两个for循环,第一个for循环遍历子数组起始位置,第二个for循环遍历对应的终止位置。时间复杂度是 O ( n 2 ) O(n^2) O(n2).
滑动窗口
为什么会考虑到用滑动窗口呢?什么是滑动窗口呢?怎么就能解决问题呢?
- 为什么用滑动窗口:暴力算法是两个for循环,考虑能否在一个for循环里面解决问题,和双指针一样。
- 什么是滑动窗口:就是两个指针之间的集合
怎么解决:
- for循环遍历的是起始指针还是终止指针?如果是起始指针,思路和暴力解法一样。所以必须是终止指针。
- 起始指针怎么移动?起始和终止指针初始位置都在0,其中元素只包含第一个。当滑动窗口中元素和大于s时,起始指针向结尾移动,缩小窗口。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = nums.size() + 1;
#if 0
// brute force
for (int i = 0; i < nums.size(); i++) {
int tmp = 0;
int count = 0;
for (int j = i; j < nums.size(); j++) {
tmp += nums[j];
count ++;
if (tmp >= target) {
result = (count < result) ? count : result;
break;
}
}
}
#endif
// 滑动窗口
int left = 0, right = 0;
int sum = 0;
int count = 0;
for (; right < nums.size(); right++) {
sum += nums[right];
while (sum >= target) {
count = right - left + 1;
result = (count < result) ? count : result;
sum -= nums[left++];
}
}
return (result == nums.size() + 1) ? 0 : result;
}
};
59.螺旋矩阵II
每一条边都要注意区间的定义。这样会让边界条件更容易处理。
所以真正解决题目的代码是简洁的,有原则性的。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n, 0));
int loop = n / 2;
int startx = 0, starty = 0;
int offset = 1;
int count = 1;
while (loop--) {
int x = startx;
int y = starty;
for (; y < n - offset; y++)
result[x][y] = count++;
for (; x < n - offset; x++)
result[x][y] = count++;
for (; y > startx; y--)
result[x][y] = count++;
for (; x > starty; x--)
result[x][y] = count++;
startx++;
starty++;
offset++;
}
if (n % 2)
result[n/2][n/2] = count;
return result;
}
};
数组总结
- 数组在内存中地址是连续的,是不能直接删除的,只能覆盖。因此容器vector的erase的时间复杂度是 O ( n ) O(n) O(n).
- 从二分查找的例子中,我们要记住搜索区间定义的重要性。
- 从移除元素中我们要掌握双指针的概念,要能够说出每一个指针所代表的实际含义,而不是背答案。
- 从长度最小的子数组中,我们也要理解滑动窗口的含义。
- 最后,螺旋矩阵再一次体现了搜索区间的精准定义,会减少很多边界条件的麻烦。