Leetcode 977-有序数组的平方 | LeetCode209-长度最小的子数组 | Leetcode59-螺旋矩阵
Leetcode 977-有序数组的平方
- 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
示例 2: 输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]
方法一-双指针法
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left = 0;
int n = nums.size();
int right = n-1;
vector <int>result(n,0); // 定义一个长度为nums.size()的动态数组
while(left<=right)
{
if(nums[left] * nums[left]<nums[right] * nums[right])
{
result[n-1]=nums[right] * nums[right]; //比较前后俩个指针指向的值将大的数从后往前排
n--;
right--;
}
else
{
result[n-1]=nums[left] * nums[left];
n--;
left++;
}
}
return result;
}
};
思考:
- 这个数组为有序数组,那么即使前面有负的,数组平方的最大值只能是在数组的倆端,不是在左边就是右边,不可能是在中间
由此想到双指针做法,left从前往后,right从后往前,将大的放在新创建数组的末端
注意循环终止的条件,这边left==right也是有意义的
方法二-暴力排序
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
for (int i = 0; i < A.size(); i++) {
A[i] *= A[i];
}
sort(A.begin(), A.end()); // 快速排序
return A;
}
};
LeetCode209-长度最小的整数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0 。
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
方法一-暴力解法
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX; //INT32_MAX可以看成一个相当大的数
int sum = 0;
int sublength = 0;
int n = nums.size();
if(n==0) return 0;
for(int i = 0;i<n;i++) //i为最小子数组的起点
{
sum = 0; //每次重新移动起点都要将sum赋值为0
for(int j = i;j<n;j++) //j为最小子数组的终点
{
sum += nums[j];
if(sum>=target) //当发现子序列超过sum的时候更新result
{
sublength = j-i+1;
result = result <sublength ? result : sublength;
break; //找到最小子序列时跳出循环
}
}
}
return result == INT_MAX ? 0 : result; //result没有被赋值的话就返回0
}
};
- 思路:用俩个for循环寻找子列
- INT_MAX = 2^31-1,INT_MIN= -2^31. 可以看出是一个相当大的数和一个相当小的数,如果想要得到数组中最小值,可以先将最小值赋值为INT_MAX ;
同理如果想要得到数组中最大值,可以先将最大值赋值为INT_MIN ;
方法二-滑动窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int sum = 0 ;//滑动窗口之和
int sublength = 0; //滑动窗口的长度
int i = 0; //滑动窗口的起始位置
int n = nums.size();
for(int j = 0; j<n;j++)
{
sum += nums[j];
while(sum>=target)
{
sublength = j-i+1;
result = result< sublength ? result :sublength;
sum -= nums[i++]; //滑动指针 从sum中减去起始位置的值并且 移动起始位置
}
}
return result==INT_MAX ? 0 : result; //判断是否能找到最小的子数组不能则返回0
}
};
思路:
利用滑动窗口(起始就是双指针)
for循环中遍历的是 窗口末端位置。为什么只用一个for循环便利就能达到预期效果呢?这边类似一个滑动的窗口,当窗口的末端位置向后移动时,满足sum>=target的条件后就要将起始位置的指针移动,满足条件的话不断更新result的值,使其能成为最小的子序列。
Leetcode59-螺旋矩阵
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0)); //使用vector定义一个二维数组
int startx = 0,starty = 0; //定义每循环一个圈的起始位置
int loop = n/2; //每个圈循环的次数
int middle = n/2; //矩阵中间的位置
int count = 1; //给矩阵中每一个空格赋值
int offset = 1; //勇于控制每一条边遍历的长度
int i,j;
while(loop--)
{
i = startx;
j = starty;
//四个for转一圈
for(j = starty;j<n-offset;j++) //上行从左到右(左闭右开)
{
res[startx][j]=count++;
}
for(i=startx;i<n-offset;i++) //右列从上到下(左闭右开)
{
res[i][j]=count++;
}
for(;j>starty;j--) //下行从右到左(左闭右开)
{
res[i][j]=count++;
}
for(;i>startx;i--) //左列从下到上(左闭右开)
{
res[i][j]=count++;
}
startx++;
starty++; //从第二圈开始起始位置都各自+1
offset+=1; //offset控制每一条边遍历的长度
}
if(n%2)
{
res[middle][middle]=count; //如果n为奇数的话,需要单独给矩阵最中间的值赋值
}
return res;
}
};
- 思路: 坚持循环不变量-每次循环里都要遵循同一套规则,必须保持一些变量的不可变。 这边始终坚持左闭右开的原则
—填充上行从左到右;填充右列从上到下;填充下行从右到左;填充左列从下到上