力扣 977.有序数组的平方
题目:
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序
题解1:暴力解法
当拿到这个题目,题意很明白,该数组是一个非递减顺序排列的整数数组,要想元素平方过后组成新的数组。如果是暴力解法的话,可以直接对数组中所有元素平方,然后直接使用快速排序sort()即可。
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;
}
};
题解2:双指针法--顺序排列的数组
此种做法需要注意,非递减顺序 排序的整数数组平方后的最大值出现在原数组两端(最左端可能有负值的情况)。
利用双指针的方法,可以直接对比两端平方后的值,如果一方大,则送入新建立的数组中,因为要求新数组结果是由小往大排列的,这地方又要注意k值是由大往小取的,目的就是把最大值放在新数组最后。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> results(nums.size() , 0); //新数组的创建,后面括号意思是与nums数组大小与向量相同,且初始化所有元素为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]){
results[k] = nums[i] * nums[i] ;
k--;
i++;
}
else{
results[k] = nums[j] * nums[j] ;
k--;
j--;
}
}
return results ;
}
};
力扣 209.长度最小的子数组
题目:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
题解1:暴力解法--超出时长限制
两个for循环直接搜索出最小的符合题意的数组,找出数组中所有组合形式,并对比。最终没过用例测试(超出时长限制)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;//最终的结果,这里的INT32_MAX是32位中的取最大值
int sum = 0;//数组元素之和
int sublength = 0 ;//数组的长度
for(int i = 0 ;i < nums.size();i++){
sum = 0 ;//每次内循环结束,这里的数组之和都需要清0;
for(int j = i ; j < nums.size(); j++){
sum = sum + nums[j];
if(sum >=target){//大于等于
sublength = j - i + 1 ;
result = result > sublength ? sublength : result ;
break;//这里是什么意思?
}
}
}
return result == INT32_MAX ? 0 :result ;
}
};
题解2:双指针---滑动窗口
这里精髓在于for循环的是滑动窗口的终点j,通过先扩大窗口的范围再缩小其范围,来达到寻找的目的,很巧妙 。
如果这里将for循环的改变设置为起点i,是不是就和暴力算法一样了,把所有存在的情况,遍历出来了。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;//设置最大值,用于后面对比
int sum = 0;
int sublength = 0;
int i = 0 ;//设置滑动窗口起点为0
for(int j = 0 ; j < nums.size() ; j++){
sum += nums[j];//累加求窗口中的元素之和
while(sum >= target){//为什么这里使用while而不是if?因为if通常只会执行一次,而while语句会执行到指定条件为假
sublength = j - i + 1;
result = result > sublength ? sublength : result ;
sum -= nums[i];
i++;//起点移动一位,缩小窗口
}
}
return result == INT32_MAX ? 0 : result;
}
};
力扣 59.螺旋矩阵II
题目:
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
题解:循环不变量
做这种题,不看解析,脑子绕的很混,不知道如何下手。
看了解析后,发现主要的问题是边界问题,以及一些旋转时候细节处理方面。
比如,圈的起始位置,n为奇数时,中间那个元素怎么处理,循环的结束条件是什么?以及用于处理边界的offset数值设计问题。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n , 0));//创建一个二维n*n的数组,并设置初始值为0
int startx = 0 ;
int starty = 0 ;//定义每个圈的循环起始位置
int loop = n / 2 ;//求出转的圈数
int mid = n / 2 ;//若n为奇数,求出其中间位置用于赋值最后一个值,例如n=3,那么中间位置的值为(1,1)
int offest = 1 ;//区间设置的是左闭右开的,后面处理边界问题用
int count = 1 ;//用于后面计数,存放到矩阵中
int i = startx;
int j = starty;
while(loop--){
//i = startx;
//j = starty;
//第一条边 自左向右 左闭右开 留下纵坐标为 n - offset
for(j = starty; j < n - offest ;j++){
res[startx][j] = count++;
}
//第二条边 自上而下 左闭右开
for(i = startx; i < n - offest ; i++){
res[i][j] = count++;
}
//第三条边 自右而左 左闭右开
for(j; j > starty ; j--){
res[i][j] = count++;
}
//第四条边 自下而上 左闭右开
for(i; i > startx ; i--)
{
res[i][j] = count++ ;
}
startx++;
starty++;//初始位置变化,开始转下一个圈
offest++;//在转第二圈时,右边界开,要注意多留一个
}
//单独判断n是不是为奇数
if(n % 2 == 1){
res[mid][mid] = count;
}
return res ;
}
};