录子训练营| DAY2 数组—977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II 数组总结

 三道题,两道一开始都没做出来呜呜

977.有序数组的平方

题目链接

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

 最开始的思路:

先平方,后排序。都用js的内置方法。sort方法的时间复杂度不确定,ECMAScript不同版本可能使用不同的排序算法。

 代码:

var sortedSquares = function (nums) {
            // 先平方
            // map方法时间复杂度是O(n)
            nums = nums.map(x => x*x);
            // 再排序,具体时间复杂度未知,但应该都大于O(n)
            nums.sort((a,b)=> a-b);
            return nums;
};

再考虑怎么才能让时间复杂度满足O(n),应该是两个指针,分别从前往后和从后往前,这样一共遍历一次数组,时间复杂度是O(n)。

代码:

        var sortedSquares = function (nums) {
            const len = nums.length;
            // 先平方
            // map方法时间复杂度是O(n)
            nums = nums.map(x => x*x);
            // 排序。双指针。并且原地不好实现,用另外一个数组用来存放结果。
            let res = new Array(len);
            let l = 0, r = len-1;
            let n=len-1;
            while(l<=r){
                if(nums[l]<nums[r]){
                    res[n--]=nums[r--];
                }else{
                    res[n--]=nums[l++];
                }
            }
            return res;
        };

209.长度最小的子数组

题目链接

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

一开始的思路,是暴力解法,即让每一个元素都作为首元素,然后寻找满足条件的子数组长度。超时

var minSubArrayLen = function (target, nums) {
            // 思路:如果所有和<target,返回0。
            let sum = nums.reduce((prev, cur) => prev + cur);
            if (sum < target) return 0;

            // 暴力解法
            let res = Infinity;
            for (let i = 0; i < nums.length; i++) {
                // i是窗口的左边界。固定左边界,这是找一个满足要求的窗口的过程。
                let j = i;
                // j是窗口的右边界
                let s = nums[i];
                while (s < target && j < nums.length) {
                    j++;
                    s += nums[j];
                }
                if (s >= target) {
                    // 找到了一个满足要求的窗口
                    let len = j - i + 1;
                    res = res < len ? res : len;
                }
            }
            return res==Infinity ? 0 : res;
  };

滑动窗口没有AC。看了解析以后才知道要固定右边界,移动左边界。

滑动窗口:就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。一个for循环,索引表示的是滑动窗口的终止位置。滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

        var minSubArrayLen = function (target, nums) {
            // 滑动窗口来做,一个for循环,循环的是右边界。
            let i=0;
            let res = Infinity;
            let s = 0;
            let len;
            for(let j=0; j<nums.length; j++){
                s += nums[j];
                while(s>=target){
                    // 满足条件了,记录一次长度
                    len = j-i+1;
                    res = res < len ? res : len;
                    // 滑动窗口的精髓:就在于此,固定右边界,不断缩小左边界。
                    s-=nums[i++];
                }
            }
            return res===Infinity ? 0 : res;
        };

59.螺旋矩阵II

题目链接

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

自己做没有AC。菜菜子···

本题是模拟数组的生成,关键是各种边界下标的处理。

        var generateMatrix = function (n) {
            // 模拟数组的生成过程
            // 几圈
            let loop = Math.floor(n/2);
            let startX = 0, startY = 0;
            let i=1;  // i记录的是第几圈
            let k=1;  //填充的数值
            let res = new Array(n).fill(0).map(x=>new Array(n).fill(0));
            while(loop--){
                // 每圈,都是上行(从左往右)-右列(从上往下)-下行(从右往左)-左列(从下往上)
                // 每圈的起始坐标、终止坐标不一样

                for(;startY<n-i;startY++){
                    res[startX][startY]=k++;
                }
                for(;startX<n-i;startX++){
                    res[startX][startY]=k++;
                }
                for(;startY>i-1;startY--){
                    res[startX][startY]=k++;
                }
                for(;startX>i-1;startX--){
                    res[startX][startY]=k++;
                }
                i++;
                startX++;
                startY++;
            }
            // 奇数,中间还剩一个空格没填
            if(n%2){
                res[startX][startY]=k;
            }
            return res;
        };

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值