- 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 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]
提示:
● 1 <= nums.length <= 104
● -104 <= nums[i] <= 104
● nums 已按 非递减顺序 排序
进阶:
● 请你设计时间复杂度为 O(n) 的算法解决本问题
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++) {
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(), nums.end());
return nums;
}
};
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
vector<int> result;
while (left <= right) {
if (nums[left] * nums[left] <= nums[right] * nums[right]) {
result.push_back(nums[right] * nums[right]);
right--;
} else {
result.push_back(nums[left] * nums[left]);
left++;
}
}
reverse(result.begin(), result.end());
return result;
}
};
题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html
视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep
209.长度最小的子数组
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
其实从动画中可以发现滑动窗口也可以理解为双指针法的一种!只不过这种解法更像是一个窗口的移动,所以叫做滑动窗口更适合一些。
在本题中实现滑动窗口,主要确定如下三点:
● 窗口内是什么?
● 如何移动窗口的起始位置?
● 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i = 0, sum = 0, minL = INT_MAX;
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
while (sum >= target) {
minL = minL < (j - i + 1) ? minL : (j - i + 1);
sum -= nums[i];
i++;
}
}
return minL == INT_MAX ? 0 : minL;
}
};
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, right = 0, sum = 0, minL = INT_MAX;
while (right < nums.size() && left <= right)
{
while (sum < target && right < nums.size())
{
sum+=nums[right];
right++;
}
while (sum >= target)
{
minL = min(right - left, minL);
sum-=nums[left];
left++;
}
}
return minL == INT_MAX ? 0 : minL;
}
};
题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。 拓展题目可以先不做。
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
文章讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
59.螺旋矩阵II
本题没有思路,第一次写不出来看懂了代码然后自己写了一遍
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
// 初始化一个n*n的矩阵,并初始化全为0
vector<vector<int>> matrix(n, vector<int>(n, 0));
// 定义4个方向的边界,初始值都为0
int top = 0, bottom = n - 1, left = 0, right = n - 1;
int num = 1;
while (top <= bottom && left <= right) {
// 从左到右填充上边界
for (int i = left; i <= right; i++) {
matrix[top][i] = num++;
}
top++;
// 从上到下填充右边届
for (int i = top; i <= bottom; i++) {
matrix[i][right] = num++;
}
right--;
// 从右到左填充下边界
for (int i = right; i >= left; i--) {
matrix[bottom][i] = num++;
}
bottom--;
// 从下到上填充左边界
for (int i = bottom; i >= top; i--) {
matrix[i][left] = num++;
}
left++;
}
return matrix;
}
};
题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。
题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
文章讲解:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html
视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/