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

本文介绍了如何使用双指针法解决LeetCode中的有序数组平方问题,以及如何利用滑动窗口技巧处理长度最小子数组问题。强调了循环不变量原则在算法设计中的重要性,通过实例展示了数组操作在内存中的特点和常见问题解决策略。
摘要由CSDN通过智能技术生成

977. 有序数组的平方

题目建议 : 本题关键在于理解双指针思想 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章讲解:代码随想录

视频讲解: 双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili

重点:相向双指针+非倒序数组最左和最右的值的平方为较大的

public static int[] sortedSquares(int[] nums) {
        // 相向双指针
        int left = 0;
        int right = nums.length - 1;
        int[] newArr = new int[nums.length];
        int newArrIndex = nums.length - 1;
        while (left <= right) {
            // 如果左指针的值的平方小于右指针的,更新新数组为右指针的值
            if (nums[left] * nums[left] < nums[right] * nums[right]) {
                newArr[newArrIndex--] = nums[right] * nums[right];
                right--;
            // 如果右指针的值的平方小于等于左指针的,更新新数组为左指针的值
            } else {
                newArr[newArrIndex--] = nums[left] * nums[left];
                left++;
            }
        }
        return newArr;
}

209.长度最小的子数组

题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。  拓展题目可以先不做。 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章讲解:代码随想录

视频讲解:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili

重点:滑动窗口,for循环的变量究竟是窗口的起始位置还是终止位置

想法:

1. for循环的变量应该是窗口的终止位置,如果是起始位置的话,相当于还是终止位置不断变化,遍历完所有元素,跟暴力破解是没区别的。

2. 既然是窗口的终止位置,我们只需要先固定好起始位置,循环改变窗口的终止位置,一旦窗口中的元素的和大于等于target,我们就可以开始移动起始位置来不断缩小窗口的大小,期间不断更新我们所记录的最小长度。如果期间窗口中的元素又小于target了,我们就移动终止位置,扩大窗口大小,再接着判断。

public static int minSubArrayLen(int target, int[] nums) {
        int result = Integer.MAX_VALUE;
        int currentWindowSize;
        int sum = 0;
        int start = 0;
        // 移动终止位置
        for (int end = 0; end < nums.length; end++) {
            sum += nums[end];
            // 不断缩小窗口大小,来查找是否又更小的数组满足条件
            while (sum >= target) {
                currentWindowSize = end - start + 1;
                result = Math.min(result, currentWindowSize);
                // 因为起始位置变化了,所以sum也要变小
                sum -= nums[start];
                start++;
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
}

59.螺旋矩阵II

题目建议:  本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章讲解:代码随想录

视频讲解:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili

重点:循环不变量原则,处理每一条边的时候,坚持左闭右开或者左闭右闭,从始至终都坚持一个

想法:坚持左闭右开原则,然后顶边->右边->底边->左边依次赋值,一圈赋值完毕后,往圈中心收缩。如果n为奇数,则需手动填写圈中心的值

public static int[][] generateMatrix(int n) {
        int[][] nums = new int[n][n];
        int startX = 0;
        int startY = 0;
        // 控制循环一轮之后,要往圈中心缩紧
        int offset = 1;
        int count = 1;
        // 要走多少圈
        int loop = n / 2;
        int i;
        int j;
        while (loop-- > 0) {
            // 处理顶上的边
            for (j = startY; j < n - offset; j++) {
                nums[startX][j] = count++;
            }
            // 处理右边的边
            for (i = startX; i < n - offset; i++) {
                nums[i][j] = count++;
            }
            // 处理底下的边
            for (; j > startY; j--) {
                nums[i][j] = count++;
            }
            // 处理左边的边
            for (; i > startX; i--) {
                nums[i][j] = count++;
            }
            // 往圈中心缩小一圈
            offset++;
            startX++;
            startY++;
        }
        // 如果为奇数,也就是最后会剩下最中心的没有填,直接填上即可
        if (n % 2 == 1) {
            nums[startX][startY] = count;
        }
        return nums;
}

数组总结

在内存中的存储方式:数组是存放在连续内存空间上的相同类型数据的集合。

 需要两点注意的是

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的。

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

数组的元素是不能删的,只能从后往前覆盖。

那么二维数组直接上图,大家应该就知道怎么回事了:

 那么二维数组在内存的空间地址是连续的么?

我们来举一个Java的例子,例如: int[][] rating = new int[3][4]; , 这个二维数组在内存空间可不是一个 3*4 的连续地址空间

看了下图,就应该明白了:

所以Java的二维数组在内存中不是 3*4 的连续地址空间,而是四条连续的地址空间组成!

数组经典题目

二分法

坚持循环不变量原则,左闭右闭或者左闭右开

双指针法

双指针法(快慢指针法):通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

滑动窗口

滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。

模拟行为

相信大家有遇到过这种情况: 感觉题目的边界调节超多,一波接着一波的判断,找边界,拆了东墙补西墙,好不容易运行通过了,代码写的十分冗余,毫无章法,其实真正解决题目的代码都是简洁的,或者有原则性的(坚持循环不变量原则),大家可以在这道题目中体会到这一点。

数组思维导图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值