977 有序数组的平方
Problem: 977. 有序数组的平方
思路
首先观察数组特性:非递减有序,题设要求是寻找平方的有序非递减排列,假如原地平方可以观察到新数组应该是一个极小值样式(先减后增)的排列,故而不难得出基本想法是双指针法。
类比27.移除元素可以发现,此处的双指针可以说是广义上的双指针:
- fast类型指针有两个,一个作用在非负数域一个作用在负数域,用于选择符合条件的新数组元素
- slow类型指针也就是结果指针,有一个,用于更新结果数组。
解题方法
如下图,使用左右的两个fast指针所指向的数平方做比较,结果集中的slow指针做结果数组的更新
复杂度
- 时间复杂度:
O ( n ) O(n) O(n) 其中n为数组长度
- 空间复杂度:
O ( 1 ) O(1) O(1) 维护常量空间(3个指针)
Code
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int size = nums.size();
vector<int> ans(size);
for(int left = 0, right = size-1, pos = size-1; left <= right;)
{
if(nums[right] * nums[right] <= nums[left] * nums[left]) {
ans[pos] = nums[left] * nums[left];
++left;
}
else {
ans[pos] = nums[right] * nums[right];
--right;
}
pos--;
}
return ans;
}
};
209 长度最小的子数组
Problem: 209. 长度最小的子数组
思路
- 首先要观察数组特性:都是正整数。这是后续解决题目的主要逻辑基础,在滑动窗口中假如没有这个条件是无法做到前向遍历递增和起始位置更新的。
- 主要想法基础还是双指针法也可以叫滑动窗口法,先前向找到一个大致的满足题设要求的终止位置,然后再对当前情况下的起始位置做更新,直到满足边界条件。之后再对终止位置向后更新,循环这个流程。
解题方法
维护 s t a r t start start和 e n d end end指针,使用while循环进行区间的缩小,需要注意我们此处需要加入中间变量 s u b l e n sublen sublen用于维护结果长度 r e s u l t result result的更新, r e s u l t result result的初始化为INT_MAX.
复杂度
- 时间复杂度:
O ( n ) O(n) O(n) 其中 n n n 是数组的长度。指针 s t a r t start start 和 e n d end end 最多各移动 n n n 次。
- 空间复杂度:
O ( 1 ) O(1) O(1) 常数级别的指针开销
Code
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int sum = 0;
for(int i=0, j=0; j<nums.size(); j++){
sum += nums[j];
while (sum >= target){
int sublength = j-i+1;
result = min(result, sublength);
sum = sum-nums[i];
i++;
}
}
return result == INT_MAX ? 0 : result;;
}
};
59 螺旋矩阵
Problem: 59. 螺旋矩阵 II
思路
基本思路是逐层分解矩阵,按照走的流程来看是上->右->下->左,处理边界的要求可以统一也可以不统一,具体要看循环的实现方式,加入四个位置变量top,bottom,left,right在每一层的遍历后更新,做边界限定。
解题方法
复杂度
- 时间复杂度:
O ( n 2 ) O(n^2) O(n2) 遍历了所有的 n 2 n^2 n2个单元格
- 空间复杂度:
O ( 1 ) O(1) O(1),维护常数个变量
Code
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int t = 0; // top
int b = n-1; // bottom
int l = 0; // left
int r = n-1; // right
vector<vector<int>> ans(n,vector<int>(n));
int k=1;
while(k<=n*n){
for(int i=l;i<=r;++i,++k) ans[t][i] = k;//上
++t;
for(int i=t;i<=b;++i,++k) ans[i][r] = k;//右
--r;
for(int i=r;i>=l;--i,++k) ans[b][i] = k;//下
--b;
for(int i=b;i>=t;--i,++k) ans[i][l] = k;//左
++l;
}
return ans;
}
};