文章讲解:
977.有序数组的平方
977. 有序数组的平方
第一想法
如果用暴力循环,时间复杂度是nlogn.
以0为分界,0左侧逐渐变大,0右侧逐渐变大,新建一个数组,用双指针把平方后的数据放进去
解题思路
同上,不过要注意一下退出循环的条件,自己写的是相等时break,其实可以直接对l ++
,然后在此循环发现不满足l <= r
.
实现代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
int l = 0, r = n - 1;
vector<int> res(n);
int m = n - 1;
for (int i = 0; i < n; i ++)
nums[i] = nums[i] * nums[i];
while (l <= r){
if (l == r){
res[m] = nums[l];
break;
}
if (nums[l] < nums[r]){
res[m --] = nums[r--];
}else{
res[m --] = nums[l++];
}
}
return res;
}
};
209. 长度最小的子数组
第一想法
用队列建立一个滑动窗口,遍历整个数组.如果和小于target,一直添加,如果发现添加后大于target,那么需要从队头删除元素,直到小于target,然后再继续添加后面的元素重复上述过程.
存在问题
需要考虑的是,当把队头元素删除后,重新重复上述过程,为什么能够保证新的队列产生符合条件会出现最小.因为题目要求的是连续数组,新添加的数前一位的数已经重复过判断过程,所以一定是向后继续进行规则判断.
解题思路
- 实现滑动窗口:队列
- 实现滑动窗口:双指针,需要注意长度如何表示
实现代码
- 优点笨拙的自我实现
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
queue<int> res;
int sum = 0;
int ans = INT_MAX;
for (int i = 0; i < nums.size(); i ++){
if (sum + nums[i] < target){
res.push(nums[i]);
sum += nums[i];
}else{
res.push(nums[i]);
sum += nums[i];
ans = min(ans, int(res.size()));
while (sum > target){
int a = res.front();
sum -= a;
res.pop();
if (sum >= target) ans = min(ans, int(res.size()));
}
}
}
if (ans == INT_MAX) return 0;
return ans;
}
};
- 优化了的双指针
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int l = 0, r = 0;
int n = nums.size();
int sum = 0;
int res = INT_MAX;
for (; r < n; r ++){
sum += nums[r];
while (sum >= target){
res = min(res, r - l + 1);
sum -= nums[l++];
}
}
if (res == INT_MAX) return 0;
return res;
}
};
59. 螺旋矩阵Ⅱ
第一思路
类似之前做过的顺序打印问题,定义完数组,如何建立规则把数据顺序填充进去.很明确n
为偶数和奇数处理方式有区别,需要进行判断.循环规则是按照螺旋,定义为[)
的方式,把每一行最后一个留给下一条规则处理.
存在问题
- 循环次数
n / 2
需要判断奇数 - 每次循环都有一个offset
代码实现
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int m = n / 2;
int x = 0, y = 0;
vector<vector<int>> res(n, vector<int> (n, 0));
int count = 1;
int t = 1;
while (m --){
int i, j;
for (j = y; j < n - t; j ++) res[x][j] = count ++;
for (i = x; i < n - t; i ++) res[i][j] = count ++;
for (; j > y; j --) res[i][j] = count ++;
for (; i > x; i --) res[i][j] = count ++;
x ++, y ++, t ++;
}
if (n % 2 == 1) res[n / 2][n / 2] = count;
return res;
}
};
数组总结
基本理解
- 数组的是行先序,按照行先分配内存,所以循环要注意
i j
的分布,提高效率. - 二维数组看似是连续的,实际上是通过指针进行地址链接,具体可以看vector实现
方法总结
二分法
留意边界问题,规则是按照[]
还是[)
决定
双指针法
滑动窗口
注意滑动窗口的规则指定
模拟行为
如何处理边界问题,首先定义好[)