977 有序数组的平方
题目链接:977 有序数组的平方
介绍
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路
看到题目的第一反应,首先负数的平方跟正数的平方是相同的,所以想到可以先将Nums中的负数变成正数,然后对其进行排序,然后再将排好序的正数进行平方。或者直接平方后,再排序。
暴力解法:
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;
}
};
双指针解法:
当对数组进行平方后还能进行一个有序的排列时,可发现,所有元素平方后由大到小的趋势:最大元素在两边。
首先可定义一个新的数组result,用于存放排列后的数。
定义一个索引下标k=num.size()-1【新的数组由大到小来更新,取两边的最大 然后取次大】
定义两个下标i,j
循环终止的条件:i<=j(如果i<j是,假设i指向的数和j指向的数相同,那么就落下了这个数)
int k=num.size()-1
for(i=0,j=num.size()-1;i<=j ; ){
//i++和j--取决于哪个对应的是最大值,如果i对应的是最大值,那么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--;
}
}
代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> results(nums.size());//注意定义数组时要在后面说明数组的长度
int k = nums.size()-1;
int i,j;
for(i=0,j=nums.size()-1;i<=j;){
if(nums[i]*nums[i]>nums[j]*nums[j]){
results[k--] = nums[i]*nums[i];
i++;
}else{
results[k--] = nums[j]*nums[j];
j--;
}
}
return results;
}
};
209 长度最小子数组
题目链接:209 长度最小子数组
介绍
思路
滑动窗口思想—双指针思路:不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
使用一个for循环做两个for循环所做的事。for循环中的下标j指向的是终止位置。而如何移动起始位置就是需要解决的问题。通过利用题中给出的条件,集合中的元素若>=s,那么即可将起始位置向后移动。通过移动起始位置去收集不同区间里面的和。
result = MAX
for(i=0,j=0;j<nums.size();j++){ //i是起始位置,j是终止位置
sum = sum + nums[j];
while(sum>=s) //持续向后移动
{
subL=j-i+1;
result = min(result,subL)
sum = sum - nums[i]
i++;
}
}
return result;
首先移动终止元素j,找到起始位置i和j之间的长度s,若s满足条件(sum>=s),则移动起始位置i,更新sum值(sum=sum-num[i])和区间长度(i++)
然后重新判断s是否满足条件,如果满足条件,继续移动其实位置i,更新sum值。如果不满足条件,则跳出while循环,移动终止位置j(j++),更新新区间的sum值(在原sum的基础上增加num[j],重新判断是否满足条件。
class Solution {
public:
int minSubArrayLen(int target, 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 = sum + nums[j];
while(sum>=target){
subLength = j-i+1;
result = result > subLength?subLength:result;
sum = sum - nums[i];
i++;
}
}
return result == INT32_MAX?0:result;
}
};
代码
59 螺旋矩阵
题目链接:59 螺旋矩阵
介绍
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
思路
问题:边界处理!
最关键:边界上的四个点。(当前边遍历时处理还是下一条边遍历时处理)
循环不变量原则:坚持一个规律来处理每一条边。
若按照左闭右开的原则:每条边只处理第一个节点,最后一个不处理。把最后一个节点留给下一条边的起始位置处理。
while(m/2){ //一共转几圈,n/2圈,如果n是奇数,对nums[][]作为单独的赋值
//每一圈的起始位置不固定
startx=0;
starty=0;
offset=1;
count=1;
//遍历第一条边 j是列
for(j=starty;j<n-offset;j++){
nums[startx][j]=count;
count++;
}
//遍历第二条边 i是行
for(i=startx;i<n-offset;i++){
//此时j=n-offset
nums[i][j]=count;
count++;
}
//遍历第三条边 j已经指向了右下角,不需要初始化了,但终止的边界是j>starty,要留给下一条边处理
for( ; j>starty;j--){
nums[i][j]=count;
count++;
}
//遍历第四条边 i已经在最下面了,也不需要初始化
for( ; i<startx;i--){
nums[i][j]=count;
count++;
}
startx++;
starty++;
offset++;
if(n%2==1){
nums[i][j]=count
}
}
代码
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;
}
};