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

977.有序数组的平方

题目链接: 977.有序数组的平方
参考文档:代码随想录
状态:已完成
耗时:一小时
思路:题目要求时间复杂度为O(n),开始花了二十分钟没有太多思路,仅想到输入数组仍是有规律可循,可以分开正数负数两部分处理。后续发现了主要突破点:题目没有要求空间复杂度,且明确要求返回数组,而不是直接用nums,因此想到了新建数组,并使用双指针的写法:

解法一

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let count = 0;
    let result = [];
    for(let i = 0; i< nums.length; i++){
        if(nums[i]<0){
            count++;
        }
        nums[i]=Math.pow(nums[i],2);
    }
    
    let j = count-1;  //j是nums中最大负数的起始节点
    let k = count;  //k是nums中最小正数的起始节点
    for(let i = 0; i< nums.length; i++){
        if((nums[j]<=nums[k] && nums[j]!= null) || nums[k]==null){  //将已经平方的更小数字放入新数组中,如果nums正数部分已经遍历完毕,则将剩下的负数部分放入新数组,else if判断同理
            result[i]=nums[j];
            j--;  
        }
        else if((nums[j]>nums[k] && nums[k]!= null) || nums[j]==null){
            result[i]=nums[k];
            k++;
        }
    }
    return result;
};

解法二:考虑到将来工作需要,也可以直接使用sort()方法解决:

var sortedSquares = function(nums) {
    for(let i = 0; i< nums.length; i++){
        nums[i]=Math.pow(nums[i],2);
    }
    nums.sort((a, b) => a - b);
    return nums;
};

这里有个坑,如果nums.sort()不带参数会按字符串大小来比较,得出来的结果未必是我们想要的,因此要写成sort((a, b) => a - b),这样就是按数字升序排序。

解法三:最后贴出代码随想录的参考答案,其实和解法一的思路是一样的,不过人家是从后往前地将元素插入新数组,这样在设置判断条件时会没这么复杂,大家也可以参考下:

var sortedSquares = function(nums) {
    let n = nums.length;
    let res = new Array(n).fill(0);
    let i = 0, j = n - 1, k = n - 1;
    while (i <= j) {
        let left = nums[i] * nums[i],
            right = nums[j] * nums[j];
        if (left < right) {
            res[k--] = right;
            j--;
        } else {
            res[k--] = left;
            i++;
        }
    }
    return res;
};

解法三的代码确实更简洁些

977.有序数组的平方

题目链接: 977.有序数组的平方
参考文档:代码随想录
状态:已完成
耗时:半小时?
思路:第一版是从前往后遍历,算出第一段大于等于target后,统计元素个数,再跳过这段继续往下面遍历,参考答案后发现该解法是错的(但是leetcode测试用例太少了,我还是通过了),因为会遗漏一部分的解,代码如下:

var minSubArrayLen = function(target, nums) {
    let count = 0;
    let min = nums.length+1;
    let sum = 0;
    for(let i=0; i<nums.length;i++){
        sum+=nums[i];
        count++;
        if(sum>=target && min>count){
            min=count;
            count=0;
            sum=0;
        }
    }
    return min==nums.length+1?0:min;
};

解法一:暴力算法,时间复杂度O(n):

var minSubArrayLen = function(target, nums) {
    let count = 0;
    let min = nums.length+1;
    let sum = 0;
    for(let i=0; i<nums.length;i++){
        count=0;
        sum=0;
        for(let j=i;j<nums.length;j++){
            sum+=nums[j];
            count++;
            if(sum>=target && min>count){
                min=count;
                count=0;
                sum=0;
                break;
            }
        }
    }
    return min==nums.length+1?0:min;
};

解法二:利用滑动区间解决问题,时间复杂度O(n):

var minSubArrayLen = function(target, nums) {
    let min = nums.length+1;
    let sum = 0;
    let j = 0;
    for(let i=0; i<nums.length;i++){  //i是快指针
        sum += nums[i];
        while(sum>=target){
            min = Math.min(min,i-j+1);
            sum = sum - nums[j];
            j++;
        }
    }
    return min == nums.length+1?0:min;
};

59.螺旋矩阵II

题目链接:59.螺旋矩阵II
参考文档:代码随想录
状态:已完成
耗时:两个小时
思路:能想到是对二维矩阵的四条边做处理,并且每条边只处理n-1个元素(这样处理每条边的时候就方便些),但是实际操作起来还是缝缝补补,靠debug补出了代码,并不可取:
代码:

var generateMatrix = function(n) {
    let matrix = new Array(n).fill(0).map(() => new Array(n).fill(0));
    let begin = 1;
    for(let i = 0;i<n/2;i++){
        if(i==Math.floor(n/2)){
            matrix[i][i]=n*n;
            break;
        }
        for(let j = i;j<n-1-i;j++){
            matrix[i][j]= begin+j;
            matrix[j][n-1-i]= begin+(n-1-i*2)+j;
            matrix[n-1-i][j+1] = begin+(n-1-i*2)*3-j;
            matrix[j+1][i] = begin+(n-1-i*2)*4-j;
            console.log("");
        }
        begin = matrix[i+1][i];
    }
    return matrix;
};

代码随想录的解法:

function generateMatrix(n: number): number[][] {
    let loopNum: number = Math.floor(n / 2);
    const resArr: number[][] = new Array(n).fill(1).map(i => new Array(n));
    let chunkNum: number = n - 1;
    let startX: number = 0;
    let startY: number = 0;
    let value: number = 1;
    let x: number, y: number;
    while (loopNum--) {
        x = startX;
        y = startY;
        while (x < startX + chunkNum) {
            resArr[y][x] = value;
            x++;
            value++;
        }
        while (y < startY + chunkNum) {
            resArr[y][x] = value;
            y++;
            value++;
        }
        while (x > startX) {
            resArr[y][x] = value;
            x--;
            value++;
        }
        while (y > startY) {
            resArr[y][x] = value;
            y--;
            value++;
        }
        startX++;
        startY++;
        chunkNum -= 2;
    }
    if (n % 2 === 1) {
        resArr[startX][startY] = value;
    }
    return resArr;
};

总结:

  1. 可以使用ai造多些测试边界的用例
  2. 缝缝补补出来的代码不能算真正完成,还是要看他人的写法,明白怎样写更合理,掌握二刷也能顺利写出的写法才算完成。有思路但因写法不对导致耗时过长应有取舍地看答案。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值