【代码训练营】day2 | 977.有序数组的平方 & 209.长度最小的子数组 & 59.螺旋矩阵II

文章介绍了LeetCode上的几个数组问题的解决方案,包括有序数组的平方使用双指针优化排序,长度最小的子数组利用滑动窗口法求解,以及螺旋矩阵II的构建方法。强调了解题思路,如暴力法的简单实现,双指针法处理平方后数组的特性,以及滑动窗口在求最小子数组长度中的应用。
摘要由CSDN通过智能技术生成

所用代码:java

有序数组的平方 LeetCode977

题目链接:有序数组的平方 LeetCode977 - 简单

思路

1、暴力法: 直接平方然后排序

public int[] sortedSquares(int[] nums) {
    for (int i = 0; i < nums.length; i++) {
        nums[i] = nums[i] * nums[i];
    }
    Arrays.sort(nums);
    return nums;
}

2、双指针法: 一个从小到大排好序的数组里面如[-5, -4, 0, 2, 4],进行平方运算的话总是会两头中间小如[25, 16, 0, 4, 16],所以可以对平方后的数使用双指针(一个指向头部,一个指向尾部),并判断两头大小,填入新数组里面。

977.有序数组的平方.gif

public int[] sortedSquares(int[] nums) {
    int head = 0;
    int rear = nums.length - 1;
    int[] temp = new int[nums.length];
    // p指针,指向新数组的最后一个位置,便可从大到小排序
    int p = temp.length - 1;
    
    // 取等,否则只有一个数[1],就不会进入循环
    while (head <= rear){
        // 判断头部还是尾部的平方谁大
        if (nums[head]*nums[head] > nums[rear]*nums[rear]){
            // 每次判断后p指针前移,头尾指针按需移动
            temp[p--] = nums[head] * nums[head];
            head++;
        }else{
            temp[p--] = nums[rear] * nums[rear];
            rear--;
        }
    }
    return temp;
}

总结

暴力解法比较简单,应该都能想到。双指针也不难,重在考虑每次比较后哪个指针应该移动,以及head ?= rear是否取等问题,这时代入一个数就好了。

长度最小的子数组 LeetCode209

题目链接:长度最小的子数组 LeetCode209-中等

思路

1、暴力解法

直接算出每一次>=target的值,但是leetcode会报超时。

public int minSubArrayLen(int target, int[] nums) {
    int res = Integer.MAX_VALUE;
    int sum = 0;
    int subLength = 0; // 子序列的长度
    for (int i = 0; i < nums.length; i++) {
        for (int j = i; j < nums.length; j++) {
            sum += nums[j];
            if (sum >= target){
                subLength = j - i + 1;
                res = subLength < res ? subLength : res;
                break;
            }
        }
        sum = 0;
    }
    return res == Integer.MAX_VALUE ? 0 : res;
}

2、滑动窗口法(推荐):

209.长度最小的子数组.gif

public int minSubArrayLen(int target, int[] nums) {
    // 窗口下沿,也就是起始位置
    int window = 0;
    int sum = 0;
    int res = Integer.MAX_VALUE;
    int subLength = 0;
    // for循环表示的是窗口的终止位置,i为窗口上沿
    for (int i = 0; i < nums.length; i++) {
        sum += nums[i];
        while (sum >= target){
            subLength = i - window + 1;
            res = subLength < res ? subLength : res;
            // 窗口下沿往前移动,减小sum的值
            sum -= nums[window];
            window ++;
        }

    }
    return res == Integer.MAX_VALUE? 0 : res;
}

总结

1、注意滑动窗口谁代表起始位置,谁代表终点位置,一般来说for循环的结束位置就是窗口的终点位置,自己设置的变量window代表的是起点位置。窗口长度用一个subLength来记录,每一次更新之后都要比较res = subLength < res ? subLength : res得到最小的窗口。

2、所犯的错误:窗口起始和终点位置分不清!

螺旋矩阵II LeetCode59

题目链接:螺旋矩阵II LeetCode59 - 中等

思路

四个循环分别走下去

public int[][] generateMatrix(int n) {
    int[][] res = new int[n][n];
    int loop = 0;
    // 控制螺旋矩阵方向 , i行,j列
    int i = 0, j = 0;
    int startx = 0; // 起始行
    int starty = 0; // 起始列
    int offset = 1; // 控制终止条件,左开右闭
    int count = 1;

    while (n/2 > loop){
        // 第一行结束,j=2,i不变;startx + n - offset保证了左闭右开
        for (j = startx;j <n - offset;j++){
            //count[startx][j] startx控制每一次开始的行数
            res[startx][j] = count++;
        }
        // 最后一列结束,i=2,j不变
        for (i = starty;i <n - offset;i++){
            res[i][j] = count++;
        }
        // 最后一行,i=2不变,结束之后j=0
        for (;j > starty;j--){
            res[i][j] = count++;
        }
        // 第一行,j=0不变,结束之后i=0
        for (;i > startx;i--){
            res[i][j] = count++;
        }
        // 结束一轮
        loop++;
        startx++;
        starty++;
        offset++;
    }

    // 奇数的情况,中间另外赋值
    if (n%2 == 1){
        res[startx][starty] = count;
    }
    return res;
}

总结

本题大致思路基本都会,但是会在一些细节上做不好,比如说起始位置改变,终止条件改变,以及一开始没有想到处理n为奇数的情况。
注意:把边界处理好,细心一点,本题就比较简单了。

数组总结

数组多采用双指针解法,可简单快速得到答案,做题的时候应细致一点,考虑多一些情况,注意不要溢出!

数组总结.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值