目录
一、977. 有序数组的平方
题目链接:力扣
文章讲解:代码随想录
视频讲解: 双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
题目:给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left = 0, right = nums.size()-1;
vector<int> ans(nums.size(),0);
int numb = nums.size()-1;
int leftvalue = nums[left]*nums[left];
int rightvalue = nums[right]*nums[right];
while(left <= right){
while(left < right && leftvalue > rightvalue)
{
ans[numb--] = leftvalue;
left++;
leftvalue = nums[left] * nums[left];
}
while(left <= right && leftvalue <= rightvalue)
{
ans[numb--] = rightvalue;
right--;
if(left > right) break; //考虑循环结束情况
rightvalue = nums[right] * nums[right];
}
}
return ans;//10:45
}
};
时间复杂度:O(n) 空间复杂度:O(1)
⏲:10:45
总结:头尾指针相向移动可同时处理首尾数据减少时间复杂度和操作量,但是无法在原数组上直接进行操作。
二、209. 长度最小的子数组
题目链接:力扣
文章讲解:代码随想录
视频讲解:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili
题目:给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0;
int numb = 0;
int min_numb = INT_MAX;
for(int begin = 0, end = 0; end < nums.size(); end++)
{
sum += nums[end];
numb++;
while (sum >= target)
{
if(min_numb > numb)
{
min_numb = numb;
}
sum -= nums[begin++];
numb--;
}
}
return min_numb == INT_MAX ? 0 : min_numb;//7:53
}
};
时间复杂度:O(n) 空间复杂度:O(1)
⏲:7:53
总结:注意三点:1.滑动窗口内的数据情况 2.滑动窗口结束情况 (一个指针单向递增为循环)3.滑动窗口的两个指针更新情况
三、59. 螺旋矩阵 II
题目链接:力扣
文章讲解:代码随想录
视频讲解:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili
题目:给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
代码:
法一:关注每个点的可走情况,制作一个方向器(方向呈顺时针),模拟走格子,当下一个位置符合条件且未走过时,即为可走位置。
法二:控制每次走的极限情况,当每个方向行走达到极限时,更改方向。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
/*法一:模拟控制小人走格子
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> ans(n,vector<int>(n,0)),fx={{0,1},{1,0},{0,-1},{-1,0}};
int next_x=0,next_y=0,f=0;
int x=0,y=0;
for(int k=1;k<=n*n;k++)
{
ans[x][y]=k;
for(int t=0;t<4;t++)
{
next_x=x+fx[f][0];
next_y=y+fx[f][1];
if(next_x>=0 && next_y>=0 && next_x<n && next_y<n && !ans[next_x][next_y])
{
x=next_x;
y=next_y;
break;
}
f=(f+1)%4;
}
}
return ans;//10:41
}
};*/
/*法二:控制墙壁*/
vector<vector<int>> ans(n, vector<int>(n, 0));
int k=1;
int x=0,y=0;
int left=0,right=n-1,top=0,bottom=n-1;//各面墙壁
while(k<=n*n)//墙推人走
{
for(y=left;y<=right;)//左闭右闭
ans[top][y++]=k++;
if(k>n*n) break;
top++;//走完墙更新
for(x=top;x<=bottom;)//左闭右闭
ans[x++][right]=k++;
if(k>n*n) break;
right--;//走完墙更新
for(y=right;y>=left;)//左闭右闭
ans[bottom][y--]=k++;
if(k>n*n) break;
bottom--;//走完墙更新
for(x=bottom;x>=top;)//左闭右闭
ans[x--][left]=k++;
left++;//走完墙更新
}
return ans;
}
};
时间复杂度:O(n^2) 空间复杂度:O(1)
总结:两个方法,操控人与操控墙。
1.操控人 (1)方向器 (2)判断位置的合法性 注意:合法条件的判断
2.操控墙 (1)墙的初值(2)墙的更新 注意:遵循循环不变量原则
个人认为法一模拟行走,更符合题目情况。