LeetCode977 有序数组的平方
题目链接:有序数组的平方
文章链接:有序数组的平方
视频链接:有序数组的平方
思路
拿到这道题第一反应就是暴力求解,用两个指针i和k同时指向数组的首元素,然后i用来遍历数组并同时进行平方,让k遍历数组的同时并接收这个平方的值,最后在调用C++的快排的算法库,最终返回有序的数组
代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int i, k = 0;
int len = nums.size();
for (i = 0; i < len; i++)
{
nums[k] = nums[i] * nums[i];
k++;
}
sort(nums.begin(), nums.end());
return nums;
}
};
总结
看了卡哥关于这题的讲解,卡哥用的是双指针,他的思路其实和Merge的思路基本上是一样的,可惜我做这道题的时候没有反应过来,主要是没有想到数组其实是有序的, 只不过负数平方之后可能成为最大数了。那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
改进后的代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(), 0);
int k = nums.size() - 1;
for (int i = 0, j = nums.size() - 1; i <= j; )
{
if (nums[i] * nums[i] > nums[j] * nums[j])
{
result[k--] = nums[i] * nums[i];
i++;
}
else
{
result[k--] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
LeetCode209 长度最小的子数组
题目链接:长度最小的子数组
文章链接:长度最小的子数组
视频链接:长度最小的子数组
思路
用两个指针i和j同时指向数组的首元素,遍历数组中所有元素之和的情况,与target比较,并记录子数组的长度,最终返回最短的数组长度。
代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i, j = 0, sum;
int len = 0;
int min = 999999999;
int size = nums.size();
while (j < size) {
sum = 0;
i = j;
len = 0;
while (i < size) {
sum += nums[i];
len++;
if (sum >= target && len < min)
min = len;
i++;
}
if (sum < target)
return 0;
j++;
}
return len;
}
};
总结
卡哥助手说我这个算法很容易超时,所以还是借鉴下卡哥的方法:滑动窗口。不得不说,滑动窗口这个思路的确很棒,把时间复杂度从O(N^2)改进到了O(N),具体思路实现建议看上方的视频链接。
改进后的代码
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
LeetCode59 螺旋矩阵Ⅱ
题目链接:螺旋矩阵Ⅱ
文章链接:螺旋矩阵Ⅱ
视频链接:螺旋矩Ⅱ
思路
没思路。。。没见过,有点懵,直接看视频讲解了
代码
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;
}
};
总结
这题并没有涉及到什么算法,而是需要靠自己手动模拟下整个题目要求的过程,非常考察代码掌握能力,还是需要不断练习的。