977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
解题思路:
方法一:暴力解法
就是先把所有元素平方,然后排序,这样时间复杂度就是排序算法的时间复杂度了
方法二:双指针法
因为数组中有负数,所以平方后值大的元素肯定是在数组两边,可以依次比较数组两边哪一个元素平方后的值大,然后按照从后往前的顺序,将大的元素写在一个新的数组后面,这样只需要遍历一遍数组就可以了,时间复杂度O(n)。
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
int k = A.size() - 1;
vector<int> result(k+1, 0);
for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
if (A[i] * A[i] < A[j] * A[j]) {
result[k--] = A[j] * A[j];
j--;
}
else {
result[k--] = A[i] * A[i];
i++;
}
}
return result;
}
};
注意事项:
for循环中结束的判定条件,i<=j。如果是i小于j,那最后只处理了i和j中的一个,会漏掉一个;i小于等于j,就会把所有元素都写进新数组。
209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
解题思路:
方法一:暴力解法
两层for循环,i和j,一个为开始指针,一个为结束指针,i每次增加1,j从i开始向后增加,这样的解法在leetcode上好像通过不了,反正我是超时了
方法二:移动窗口
就是这个子集范围就像是一个可以移动和变化的窗口,从前向后滑动。一层for循环,定义j为这个窗口的结束指针,从0开始循环,当sum大于target,j值停止变化,然后sum减去窗口开始的指针i元素的值,看是否sum还是大于target,如果是那继续sum减去的这一过程,直到sum再次小于target,记录最后一次的元素个数,记录i值;窗口继续向后滚动,j值继续变化;循环到j遍历整个数组。
改图引用自:代码随想录
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i=0,j;
int min = INT_MAX; //这个是要表示符合条件的最小元素个数,要取最小值,所以初始值无限大
int sum = 0;
for(j=0;j<nums.size();j++){
sum += nums[j];
while(sum>=target){
int k = j-i+1;
min = min<k?min:k;
sum -= nums[i];
i++;
}
}
return min == INT_MAX?0:min; //若数组所有元素和小于target,则返回0
}
};
59.螺旋矩阵II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n * n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
解题思路:
要按圈填入数据,想要循环起来。就必须找到一个适用于每一圈的填数公式。这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
此图来自代码随想录。
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。这也是坚持了每条边左闭右开的原则。
//这是我本人写的代码,少了一些相同的参数,详细的可以看下面的代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int i ,j ;
vector<vector<int>>Matrix(n,vector<int>(n,0));
int num = 1,line = 1;
int loop = n/2;
while(loop--){
j=line-1;
i=line-1;
for(j=line-1;j<n-line;j++){
Matrix[i][j] = num++;
}
for(i=line-1;i<n-line;i++){
Matrix[i][j] = num++;
}
for(;j>line-1;j--){
Matrix[i][j] = num++;
}
for(;i>line-1;i--){
Matrix[i][j] = num++;
}
line++;
}
if(n%2 == 1){
Matrix[n-line][n-line] = n*n;
}
return Matrix;
}
};
讲解详细代码
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; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 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++;
}
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 1;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2) {
res[mid][mid] = count;
}
return res;
}
};