977.有序数组的平方
文章链接:977.有序数组的平方
视频链接:双指针法经典题目 | LeetCode:977.有序数组的平方
题目描述
977.有序数组的平方
题解
解法一:暴力法
将各元素平方后令数组进行排序。
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;
}
};
时间复杂度:O(n + nlogn)
空间复杂度:O(1)
解法二:双指针法
由于数组有序排列且包含负数,以[-3, -2, -1, 0, 1, 2, 3]为例,数组平方最大值仅可能位于数组左端或右端。
令i指针指向数组左端,j指针指向数组右端,分别比较两元素平方,将较大值置于新数组右端后将该指针向中间移动一位,以此类推直至i > j。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> result(nums.size(), 0);
for (int i = 0, j = nums.size() - 1; i <= j;) {
if (nums[i] * nums[i] < nums[j] * nums[j]) {
result[k] = nums[j] * nums[j];
k--;
j--;
}
else {
result[k] = nums[i] * nums[i];
k--;
i++;
}
}
return result;
}
};
时间复杂度:O(n)
空间复杂度:O(n)
209.长度最小的子数组
文章链接:290.长度最小的子数组
视频链接:拿下滑动窗口! | LeetCode 209 长度最小的子数组
题目描述
290.长度最小的子数组
题解
解法一:暴力法
通过双层for循环遍历任意两元素组成的所有区间,比较得出满足元素和大于等于target的最小区间长度。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum, len, minLen = INT_MAX;
for(int i = 0; i < nums.size(); i++) {
sum = 0;
for(int j = i; j < nums.size(); j++) {
sum += nums[j];
if(sum >= target) {
len = j - i + 1;
if(len < minLen) minLen = len;
break;
}
}
}
return minLen == INT_MAX ? 0 : minLen;
}
};
时间复杂度:O(n^2)
空间复杂度:O(1)
解法二:滑动窗口(双指针法)
- 令j指向区间终止位置,i指向区间起始位置。
- 以终止位置j作为for循环索引。遍历以j为终点的各区间,区间各元素之和为sum。
- 外层for循环j由左至右遍历数组各元素。若sum大于等于target,则计算区间长度len并与最短区间长度minLen进行比较,len小于等于minLen则更新minLen并左移i,重复上述过程直至sum小于target,则左移j,以此类推直至j = nums.size()。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i = 0, len, minLen = INT_MAX, sum = 0;
for(int j = 0; j < nums.size(); j++) {
sum += nums[j];
while(sum >= target) {
len = j - i + 1;
if(len <= minLen) {
minLen = len;
}
sum -= nums[i];
i++;
}
}
return minLen == INT_MAX ? 0 : minLen;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
j总共移动n次,i在最坏情况下也移动n次,故时间复杂度为O(2n),省略常数项系数后时间复杂度为O(n)。
另:
4. LeeCode解答错误代码及其错误原因。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i, len, minLen = INT_MAX, sum = 0;
// 应于此处令i = 0,i最初指向最左端元素,往后i仅向右移动,不再回溯。
for(int j = 0; j < nums.size(); j++) {
i = 0;
/*
执行失败, 应删除该行代码,并在进入该循环前令i = 0。
以target = 7,[2, 3, 1, 2, 4, 3]为例,第一次更新minLen时为i = 0,j = 3,sum = 8
执行一次sum -= sum[0]后sum = 6,sum < target跳出循环时i重新指向最左端元素,
此时sum并非i = 0, j = 4对应区间和,而是i = 1,j = 3对应区间和。
且若每次循环i重置为0并逐个计算sum,则该算法时间复杂度为O(n^2),不再为线性时间复杂度。
*/
sum += nums[j];
while(sum >= target) {
len = j - i + 1;
if(len < minLen) {
minLen = len;
}
sum -= nums[i];
i++;
}
}
return minLen == INT_MAX ? 0 : minLen;
}
};
59.螺旋矩阵Ⅱ
文章链接:59.螺旋矩阵Ⅱ
视频链接:一入循环深似海 | LeetCode:59.螺旋矩阵II
题目描述
59.螺旋矩阵Ⅱ
题解
本题不涉及任何算法,即模拟题目求解过程。
应遵循循环不变量原则。本题不变量为各边处理规则,各边均遵循左闭右开(即各边最后一个节点由下一条边进行处理)。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
int startX = 0, startY = 0; // 起始位置为res[startX][startY]
int loop = n / 2;
int offset = 1; // 每次循环遍历至所在边的第n - offset个结点
int i, j; // 二维矩阵res[i][j]
int count = 1;
while(loop--) {
// 由左至右
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++;
offset++;
}
if(n % 2) {
res[n/2][n/2] = count;
}
return res;
}
};
时间复杂度:O(n^2)
空间复杂度:O(1)
该题本质上即遍历二维矩阵,时间复杂度为O(n^2)。
后记
啊总算又一天。:’
第二题因为找bug搁置了好久。
对代码的执行细节掌握得不太好呢,加油加油。
待完成