1.有序数组的平方:
第一思路时3个for循环,一个用来平方2个用来排序(时间复杂度不够)
暴力解法和我的思路一样,不过他用了sort函数(sort()函数可以对给定区间所有元素进行排序。它有三个参数sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,cmp参数可以不写,如果不写的话,默认从小到大进行排序)
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
for (int i = 0; i < A.size(); i++) {
A[i] *= A[i];
}
sort(A.begin(), A.end()); // 快速排序
return A;
}
};
双指针法:
看了思路马上就能打出来,还是很好理解的。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int>result(nums.size(),0);
int k=nums.size()-1;
int i=0,j=nums.size()-1;
while(i<=j){
if(nums[i]*nums[i]>=nums[j]*nums[j]){
result[k--]=nums[i++]*nums[i];
}
else{
result[k--]=nums[j--]*nums[j];
}
}
return result;
}
};
不知道为什么i++和j--写里面就错了?
因为result[k--]=nums[i++]*nums[i]中第一个nums[i++]=nums[i],然后i=i+1了,后面那个nums[i]和前面那个nums[i]不一样了,可以改成result[k--]=nums[i]*nums[i++]。
2.长度最小的子数组:
看了用滑动窗口这个提示,尝试写了一下,结果超时了(答案没有问题)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int first=0,end=0,a=0;
while(1){
int sum=0;
for(int i=end;i<=first;i++){
sum+=nums[i];
}
if(sum>=target)break;
first++;
end++;
if(end==1&&first==nums.size()){
return 0;
}
if(first==nums.size()){
++a;
first=a;
end=0;
}
}
return first-end+1;
}
};
滑动窗口是根据自己sum的大小来调整起始位置,终止位置。
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;
}
};
暴力解法是用两个for循环从全部情况中找到那个最短的那个。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
sum = 0;
for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
sum += nums[j];
if (sum >= s) { // 一旦发现子序列和超过了s,更新result
subLength = j - i + 1; // 取子序列的长度
result = result < subLength ? result : subLength;
break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
不过 这句别漏了。
break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
3.螺旋矩阵||
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int h=0,l=0;
int numh=n-1;
int numl=n;
int fl=1;
int fh=1;
int f=1;
for(int i=1;i<=n*n;i++){
if(f==1&&l<numl&&l>=0){
res[h][l]=i;
l=l+fl;
}
if(l==numl||l==-1){
numl--;
f=0;
l=l-fl;
h=h+fh;
fl*=-1;
}
if(h<=numh&&f==0&&h>=0){
res[h][l]=i;
h=h+fh;
}
if(h==numh+1||h==-1){
numh--;
f=1;
h=h-fh;
l=l+fl;
fh*=-1;
}
}
return res;
}
};
我的想法是利用fl,fh,f三个开关来控制赋值的方向,fl=1右,fl=-1左,fh=1下,fh=-1上,f=1控制l,f=-1控制fh。
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;
}
};
一圈里面执行4条边的赋值如果n为基数,中心单独赋值 ,这里赋值一条边是左闭右开的。