目录
一、有序数组的平方
链接:力扣1
描述:给你一个按非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
思路:
1.可以先对原数组遍历数据,再求平方,再进行排序。
2.利用双指针法。数组里可能包含有负数,由于nums数组是非递减顺序的,平方后的最大值只可能出现在两端,可考虑两个指针由两端向内部遍历,注意,本题是按非递减顺序来输出,所以新数组的下标要从大到小。
注意事项:
1.while循环里left=right也可以。
2.vector容器需要设定容器大小。
3.若存在right和left指向的值相等,取其中任意一个都行,另一个在下一次循环中会作为较大值被添加到新数组中。
4.本题使用了for_each遍历容器,需要加头文件<algorithm>
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution
{
public:
vector<int> sortedSquares(vector<int>& nums)
{
vector<int>result;
result.resize(nums.size());
int n = result.size()-1;
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
if (pow(nums[right], 2) > pow(nums[left], 2))
{
result[n--] = pow(nums[right], 2);
right--;
}
else
{
result[n--] = pow(nums[left++], 2);
}
}
return result;
}
};
void printvector(int elem)
{
//打印容器里的元素
cout << elem << " ";
}
int main()
{
vector<int>v = { -7,-3,2,3,11 };
Solution s;
vector<int>result = s.sortedSquares(v);
for_each(result.begin(), result.end(), printvector);
return 0;
}
结果如下:
二、长度最小的子数组
链接:力扣2
描述:给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
思路:
1、使用暴力求解,用两个for循环得到所有的数组的子数组,并求和来判断是否大于或等于target,满足条件则求出子数组的长度。
2、动态窗口。只用一个for循环,不断调节子数组的起始位置和终止位置。那么问题在于确定以下三方面:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口内是满足和大于等于target的元素。
如果当前的窗口内的元素满足要求了,则缩小窗口,即需要不断减少元素,从而窗口内的元素和不断减小,对应于一个while循环,里边起始位置i增大。当循环终止时,得到最小的子数组长度。
1.暴力求解代码如下:
时间复杂度为,在LeetCode里ac不了,提示超时。
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
int minSubArrayLen(int target, vector<int>& nums)
{
//暴力求解
int sublength = 0;//子数组的长度
int result = INT32_MAX;//最后的结果
int sum = 0;
for (int i = 0; i < nums.size(); i++)
{
sum = 0;
//i是起始,j是终止
for (int j = i; j < nums.size(); j++)
{
sum += nums[j];
if (sum >= target)
{
sublength = j - i + 1;
result = result < sublength ? result : sublength;
break;//退出该内层循环,因为多加没有意义了
}
}
}
return result == INT32_MAX ? 0 : result;
}
};
int main()
{
vector<int>v{ 1,1,1,1,5,8,9 };
Solution s;
int ret=s.minSubArrayLen(10, v);
return 0;
}
2.动态窗口法代码如下:
注意:
while (sum >= target)中不能使用if判断,因为需要不断去更新i的位置,如果改了的话,会导致得到的子数组长度不是最小。
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
int minSubArrayLen(int target, vector<int>& nums)
{
int i = 0;//窗口的起始位置
int sublength = 0;//子数组的长度
int sum = 0;
int result = INT32_MAX;//最终的子数组长度
for (int j = 0; j < nums.size(); j++)
{
//j是窗口终点位置
sum += nums[j];
while (sum >= target)
{
sublength = j - i + 1;
result = result < sublength ? result : sublength;
sum -= nums[i++];
}
}
return result == INT32_MAX ? 0 : result;
}
};
int main()
{
Solution s;
vector<int>v = { 1,2,3 };
int ret=s.minSubArrayLen(5,v);
return 0;
}
运行结果如下:
三、螺旋矩阵
链接:力扣3
描述:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
思路:
把握循环不变量原则:对于矩阵每一条边的处理要一致,左闭右开或者左闭右闭。
用二维容器来接收。矩阵的产生过程如下:
当n为奇数时,需要对于中间元素单独处理。
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
注意
1.需要设置一个偏移量,每次循环后需要加1,开始的x和y下标也要随着更新。
2.循环次数为n/2。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
vector<vector<int>> generateMatrix(int n)
{
//二维容器,初始化为n个一维容器,且初值为0
vector<vector<int>>res(n, vector<int>(n, 0));
int startx = 0;//开始的x下标
int starty = 0;//开始的y下标
int mid = n / 2;//用于n为奇数的情况
int i, j=0;
int count = 1;
int offset = 1;//偏移量
int loop = n / 2;//转圈次数
while (loop)
{
i = startx;
j = starty;
for (j = starty; j < n - offset; j++)
{
//不包含每一条边界的最后一个元素
res[i][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 += 1;
loop--;
}
if (n % 2 == 1)
//奇数的情况需要单独讨论
res[mid][mid] = count;
return res;
}
};
int main()
{
vector<vector<int>>v;
Solution s;
v = s.generateMatrix(1);
return 0;
}
运行结果: