6.29 代码随想录训练营第二天 | 数组题目练习:977有序数组的平方, 209长度最小的子数组,59螺旋矩阵II

今天继续来做有关数组的题目,一共是三题

第一题
977、有序数组的平方
这道题的题目是给你一个从小到大排序的数组,要求你将数组里的每个数变成这个数的平方,并且还是以从小到大的顺序排列。对于这道题我们可以用双指针来解决,当然也可以尝试一下暴力解法。

方法一:暴力解法
这个方法的逻辑很简单,就是将数组里的每个数进行平方后,然后再排序一下。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for (int i = 0; i < nums.size(); i++) {//遍历数组
            nums[i] *= nums[i];//平方
        }
        sort(nums.begin(), nums.end()); // 从小到大排序
        return nums;
    }
};

方法二:双指针
有题目可知,数组是由小到大排列的,所以我们可以将一个指针设置在index 为0时,另外一个设置在数组的末尾。这样一来几句方便我们比较负数的平方与正数的平方。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
       int i = 0, j = nums.size() - 1, k = j;//设置指针i、j,k是新的vector里面平方放入的位置
       vector<int> output(nums.size(), 0);//创建一个新的nums大小的vector,并且每一个的值为0
       while(i <= j) {//
           if(abs(nums[i]) < abs(nums[j])) {//比较两个数绝对值的大小
               output[k--] = nums[j] * nums[j];//如果是数组右边的数大,那么就在新的vector以从右到左的顺序放入平方并更新k值
               j--;//更新指针j的值
           }
           else {
               output[k--] = nums[i] * nums[i];//如果是数组左边的数大,那么就在新的vector以从右到左的顺序放入平方并更新k值
               i++;//更新指针i的值
           }
       }
       return output;//返回新的数组
    }
};

本题重点:
这道题的重点在于负数的平方变成了正数,这个时候就要进行一个排序了。因此我们利用数组是从小到大排列的特性将指针设置在数组的两端,并根据两个数的平方比较来更新指针。另外创建一个新的额vector按照从右到左的顺序将平方放入,就不需要像暴力解法那样再将数组排序一遍。


第二题
209、长度最小的子数组
这道题的题目是给你一个数以及一个数组,你将数组里的数相加能够正好等于或者大于题目给的数,并且这个几个相加的数在数组里面是连续的,并且在数组里的长度最小。这道题可以用滑动窗口(sliding window)来做,类似于双指针,但要不断的调整子数组的起始位置和结束位置。

解题思路:
设置两个指针都从index 为0开始,并且设置一个最小值为INT_MAX以便我们之后更新新的最小值。然后我们遍历数组,并与题目给的数进行比较,数组里一些数的和比题目的数要大或者相等,那么就使用两个指针的差值并加1算出长度。如果比min存储的值要小那么就成为新的min,之后让总和减去慢指针指向的那个数。 最后返回的时候如果我们设置的最小值里面的值没变就说明没有找到,返回0;反之返回最小值。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    int j = 0, sum = 0, min = INT_MAX;//设置慢指针,总和以及最小值
    for(int i = 0; i < nums.size(); i++) {//快指针i遍历数组
        sum += nums[i]; //更新总和
        while(sum >= target){//找到大于target的总和
            if(min > i-j+1) min = i-j+1;//更新最小长度
            sum -= nums[j++];//更新总和
        }
    }
        return min == INT_MAX? 0 : min;//判断返回0还是返回最小值
    }
};

第三题
59、螺旋矩阵II

Input: n = 3
Output: [[1,2,3],[8,9,4],[7,6,5]]

这题的题目是给你一个数字n,生成一个nxn的矩阵,以上图这种螺旋的方式进行填数从1-n^2。我们从图中可以看出填数的方式很明显就是先从左到右,再从上到下,再从右到左,然后就是从下到上。因此这道题就是将这四个步骤重复。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n,0));//定义一个vector数组
        int sx =0, sy =0;//定义横向和纵向起始位置
        int count = 1; //填入的数字从1开始
        int off = 1; //控制遍历的长度,从第一圈开始右边界减1,第二圈右边界减2,以此类推
        int loop = n /2; //循环四个步骤的次数
        int mid = n/2;//矩阵的中间位置
        int i,j;
    while(loop--){
        i = sx;
        j = sy;
        for(j = sy; j < n - off; j++){//从左到右
            res[sx][j] = count++; //填入数字并更新数字
        }
        for(i = sx; i < n -off; i++){//从上到下
            res[i][j] = count++;//填入数字并更新数字
        }
        for(; j > sy;j--){//从右到左
            res[i][j]=count++;//填入数字并更新数字

        }
        for(; i> sx;i--){//从下到上
            res[i][j]=count++;//填入数字并更新数字
        }
        sx++;//更新横向起始位置
        sy++;//更新纵向起始位置
        off++;//更新边界减去的长度
    }
    if(n%2) res[mid][mid]=count;//当n为奇数的时候我们要手动填入最中间的数
    return res;//返回结果
    }
};

本题重点:
这道题的算法很简单就是重复四个步骤,但是要注意的是在何时重复着四个步骤,以及什么时候停止重复。所以我们可以使用loop = n / 2来限定步骤重复的次数。除此之外,我们还要注意在每个步骤中,横向和纵向的遍历都是n - off避免重复填入数字。最后就是如果n为奇数,我们就要在矩阵的中间手动填入最后的数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值