代码随想录第二天|数组part02

开始时间10:30

209.长度最小的子数组

题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。 拓展题目可以先不做。
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
文章讲解:https://programmercarl.com/0209.长度最小的子数组.html
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE

题目感想:
题目讲解中很精髓的一句话,滑动窗口其实就是双指针,这个让我很好理解,首先因为要进行滑动,所以我们的循环代表的指针用来决定窗口结束位置,每次right指针向右一动一位,我们就把这一位加入sum,直到sum大于等于目标值,此时我们统计两个指针之间的距离,并和之前保留的距离相比,如果更小则更新最短距离,然后我们需要将sum减去left指针所在的数值,left向右移动一位,之后再进行sum比较的循环,如果小于目标值,则right继续滑动,又将新的数值添加进sum,再次进入sum比较循环,如此反复,直到right指针到了数组末尾无法继续移动;

 int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= s) {
                result = Math.min(result, right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;

59.螺旋矩阵II

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

题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
文章讲解:https://programmercarl.com/0059.螺旋矩阵II.html
视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/

题目感想:
1.首先就是面对循环时一定要遵循循环不变量原则,我的理解是如果有多个循环,然后你又不遵循循环不变量,那么每个循环拿到前一个循环传过来的值的时候,想要进行处理就得又重新写一套逻辑,之后每个循环都需要重新写,而且还不是统一的逻辑,不仅让数据处理的难度大大上升,同时代码的可复用程度大大下降,所以为了降低逻辑设计的复杂度,我们要保证每个变量的更新以及截止是有统一标准的;
2.然后就是我们要确定循环的思路,大体思路是,一圈一圈循环,然后就是每一圈都会有上下左右四个循环,为此,我们需要的循环逻辑有了,然后就是定义所需要的变量,循环的圈数(这里要注意,循环的最大圈数是二维数组阶数/2),遍历用的i,j也就是横纵坐标,每一圈遍历的起始点同时也是用来控制上下左右循环的截止变量,还有控制每圈遍历的长度的offset(其实可以用圈数来,不过单独弄一个变量来表示会更加清楚),最后要考虑特殊情况,也就是二维数组是奇数阶,最中心的那个位置需要我们单独进行填充;

 int[][] nums = new int[n][n];
        int startX = 0, startY = 0;  // 每一圈的起始点
        int offset = 1;
        int count = 1;  // 矩阵中需要填写的数字
        int loop = 1; // 记录当前的圈数
        int i, j; // j 代表列, i 代表行;

        while (loop <= n / 2) {

            // 顶部
            // 左闭右开,所以判断循环结束时, j 不能等于 n - offset
            for (j = startY; j < n - offset; j++) {
                nums[startX][j] = count++;
            }

            // 右列
            // 左闭右开,所以判断循环结束时, i 不能等于 n - offset
            for (i = startX; i < n - offset; i++) {
                nums[i][j] = count++;
            }

            // 底部
            // 左闭右开,所以判断循环结束时, j != startY
            for (; j > startY; j--) {
                nums[i][j] = count++;
            }

            // 左列
            // 左闭右开,所以判断循环结束时, i != startX
            for (; i > startX; i--) {
                nums[i][j] = count++;
            }
            startX++;
            startY++;
            offset++;
            loop++;
        }
        if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值
            nums[startX][startY] = count;
        }
        return nums;
    }

区间和
前缀和是一种思维巧妙很实用 而且 很有容易理解的一种算法思想,大家可以体会一下

文章讲解:https://www.programmercarl.com/kamacoder/0058.区间和.html

题目感想:
1.区间和就是输入一个数组然后求某两个索引之间的数字的总和,我们在输入的时候,就对数量进行累加,设定一个sum,每输入一个数字就往区间和数组里面加,加了之后区间和数组的索引就向右移动,如此反复;
2.需要注意的是,如果给的索引是0和某个索引,那直接就能得出来了,不用多说,如果给的是两个非0索引,那我们需要考虑好如何算,如3和7,3所在的数字需要包括在内的,所以我们需要用7的区间和减去2的区间和,理解不了的自己画图就明白了。
3.由于是acm需要自己处理输入输出,这个需要注意一下,下面的代码是基于输入的索引先输入左边的再输入右边的写的,如果需要拓展那就自己加逻辑
4.区间和就是把能算的先进行了计算,简化了后续的遍历统计计算,反应更快了

Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt();
        int[] vec = new int[n];
        int[] p = new int[n];

        int presum = 0;
        for (int i = 0; i < n; i++) {
            vec[i] = scanner.nextInt();
            presum += vec[i];
            p[i] = presum;
        }

        while (scanner.hasNextInt()) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();

            int sum;
            if (a == 0) {
                sum = p[b];
            } else {
                sum = p[b] - p[a - 1];
            }
            System.out.println(sum);
        }

        scanner.close();
    }

开发商购买土地
https://www.programmercarl.com/kamacoder/0044.开发商购买土地.html
题目感想:
1.一开始没怎么看懂怎么进行划分,后面才知道只能划一次,要么纵向要么横向,所以我们可以从横纵两个方面分开讨论,看看能不能的出最小的差;
2.土地差值就是土地的总份额-左边的份额=右边的份额,再用右边的份额-左边的份额得出差值,连起来就是土地总份额-左边的份额*2,这是纵向切割的,横向切割的同理可得;
3.统计部分就是先算出每一行和每一列的土地份额,之后在依此比较差值即可;

 Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int sum = 0;
        int[][] vec = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                vec[i][j] = scanner.nextInt();
                sum += vec[i][j];
            }
        }

        // 统计横向
        int[] horizontal = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                horizontal[i] += vec[i][j];
            }
        }

        // 统计纵向
        int[] vertical = new int[m];
        for (int j = 0; j < m; j++) {
            for (int i = 0; i < n; i++) {
                vertical[j] += vec[i][j];
            }
        }

        int result = Integer.MAX_VALUE;
        int horizontalCut = 0;
        for (int i = 0; i < n; i++) {
            horizontalCut += horizontal[i];
            result = Math.min(result, Math.abs(sum - 2 * horizontalCut));
        }

        int verticalCut = 0;
        for (int j = 0; j < m; j++) {
            verticalCut += vertical[j];
            result = Math.min(result, Math.abs(sum - 2 * verticalCut));
        }

        System.out.println(result);
        scanner.close();

作者:Yingc

出处:https://www.cnblogs.com/yingcn/p/18742822

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

怕什么真理无穷,进一寸有一寸的欢喜 ———— 胡适

posted @   颍川凛子  阅读(158)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示