代码随想录算法训练营第二天|977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵

有序数组的平方:977. 有序数组的平方 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/squares-of-a-sorted-array/

解题思路: 
  • 暴力解法:遍历数组使每个元素平方再用sort排序,时间复杂度为O(nlogn)取决于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;
    }
};
  • 双指针解法: 已知数组是非递减的有序数组,也就是说是从小到大的顺序,但是数组中不排除负数,所以所有数平方之后数组就会呈现中间小两边大的顺序,也就是说最大数要么在左边要么在右边,将两个指针i和j分别指向数组的开头和结尾并将两个指针向中间移动靠拢,再定义一个新数组来存放结果,只要 i<=j 就让 nums[i]^2 和 nums[j]^2 比较,大的放入新数组的最后一个位置。

具体代码如下: 

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int len = nums.size();
        int i = 0,j = len - 1;//将两个指针分别放在数组的开头和结尾
        vector<int>arr(nums.size(),0);
        int k = len - 1;
        while(i <= j){//将两个指针分别向中间靠拢
            if(nums[i] * nums[i] > nums[j] * nums[j]){
                arr[k--] = nums[i] * nums[i];
                i++;//两数平放相比先将大数放入这个新数组的后面
            }else{//如果两个数的平方相等那么不管先将哪个数放进去都一样
                arr[k--] = nums[j] * nums[j];
                j--;
            }   
        }
        return arr;
    }
};

长度最小的子数组: 209. 长度最小的子数组 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/minimum-size-subarray-sum/description/

解题思路:
  • 暴力解法:先将result赋予一个最大值,用两层 for 循环,i 表示起始位置,j 表示终止位置,用第一层 for 循环遍历数组,第二层 for 循环将数组起始位置到终止位置的和求出与 target 比较,若大于等于 s 就将从起始位置到终止位置的长度记录下来赋给 len ,比较 len 和 result 大小,将小的赋给 result。最后如果result还等于初始值就返回0,否则就返回result。
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX;
        int sum = 0,len = 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 >= target){
                    len = j - i + 1;//子序列和超过sum之后就将此时子序列的长度记录下来
                    result = result > len ? len : result;//更新result的值
                    break;//一旦找到符合条件的最短子序列,就跳出循环
                }
            }
        }
        return result == INT_MAX ? 0 : result;
    }
};
//因为力扣的数据库更新,此方法已超出时间限制

 

  • 滑动窗口解法 :滑动窗口就是不断调节子序列的起始位置和终止位置,先将起始位置暂时定住,用 j 表示终止位置,遍历数组将 j 指向的元素依次相加得到一个和,只要和大于等于target,就将j此时指向元素到其实元素的长度记录下来,与最大值 result 比较,小的那个赋给result 并将得到的和中的起始位置指向的元素减去,将 i 移动到下一位,最后返回被赋值后的result。

 具体代码如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX;
        int sum = 0,len = 0,i =  0;
       for(int j = 0;j < nums.size();j++){
           sum += nums[j];
           while(sum >= target){
               len = j - i + 1;
               result = result > len ? len : result;
               sum = sum - nums[i++]; //改变窗口的起始位置,只要和是大于等于指定数字的就将i指向元素删去
           }
       }
        return result == INT_MAX ? 0 : result;
    }
};

温馨提示:如果看完代码还不明白可以调试一下看看具体过程,也可以自己在纸上倒腾一遍,大家加油! 

相关题目:904、76

螺旋矩阵:

59. 螺旋矩阵 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/spiral-matrix-ii/description/

解题思路:

这个题使用的思想是循环不变量的思想,也就是先定位号自己的区间是左闭右闭还是左闭右开,这点与二分查找 中使用的思想很相似,在螺旋矩阵这里我们采用左闭右开的思想,将矩阵每行或每列的最后一个点交给相邻的列或行。还有一点就是矩阵n是奇数还是偶数,如果是奇数,这种左闭右开的形式势必会使中间的一个坐标为行标和列表相等(nums[n][n])的位置空出来,所以当n是奇数时,单独给中间空出来的赋值。

 

具体代码如下:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>>nums(n,vector<int>(n,0));
        int startx = 0,starty = 0;
        int mid = n / 2;//如果n为奇数,mid表示最中间那个
        int loop = n / 2;//代表要转的圈数
        int offest = 1;//表示每条边要遍历的长度,每条边缩进一位
        int count = 1;//每位要填的数
        while(loop--){
            int i = startx,j = starty;
            for(j = starty;j < n - offest;j++){//首先是要填的矩阵行不变,列增加
                nums[i][j] = count++;
            }
            for(i = startx ; i < n - offest;i++){//列不变,行增加
                nums[i][j] = count++;
            }
            for(j = n - offest;j > starty;j--){
                nums[i][j] = count++;
            }
            for(i = n - offest;i > startx;i--){
                nums[i][j] = count++;
            }
            startx++;//每转一圈,起始值都会加1
            starty++;
            offest++;//每转一圈,缩进的位数就增加1
        }
        if(n % 2 != 0){
            nums[mid][mid] = count;
        }
        return nums;
    }
};
//本题主要考察的其实没有什么算法,就是模拟转圈的过程,本题时顺时针填数,大家可自行试一下逆时针。
相关题目:54、29

算法训练第二天,感觉稍微有一点吃力,继续加油! 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值