代码随想录算法训练营DAY02 数组part02

977 有序数组的平方

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

思路:双指针法,一个指向头元素,一个指向尾元素。从尾元素开始放数据

class Solution {
    public int[] sortedSquares(int[] nums) {
        int tail = nums.length - 1;
        int head = 0;
        //存放在一个新的数组里
        int[] result = new int[nums.length];
        int index = result.length - 1;
        while (head <= tail) {
            if (nums[head] * nums[head] > nums[tail] * nums[tail]) {
                result[index--] = nums[head] * nums[head];
                ++head;
            } else {
                result[index--] = nums[tail] * nums[tail];
                --tail;
            }
        }
        return result;
    }
}

209 长度最小的子数组

​ 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

思路:滑动窗口思想。这道题建议自己手动画图理解一下。感觉也有点像双指针的用法。

​ for循环内是尾指针end,需要遍历数组内的元素。为什么不选头指针在for循环内是因为头指针遍历完后,尾指针还是需要再遍历一遍,跟暴力拆解法没有区别

public class MinSubTest {
    public int minSubTest(int[] nums,int target){
        int sum = 0;
        //需要取一个最大值,只有是最大值的时候,才能不断去更新
        int result = Integer.MAX_VALUE;
        int start = 0;

        for (int end = 0; end < nums.length; end++) {
            //存放滑动窗口元素的值
            sum += nums[end];
            while(sum >= target){
                /**
                 * 获取最小值
                 * end-start+1 是滑动窗口的长度
                 */
                result = min(result,end-start+1);
                //当sum >= target的时候,向右移动 故需要减去头指针位置上的值
                sum -= nums[start++];
            }
        }
        return result==Integer.MAX_VALUE?0:result;
    }
}

59 螺旋矩阵||

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

思路:这道题一定要画图,边界要找好。遵循循环不变量

class Solution {
    public int[][] generateMatrix(int n) {
         int[][] arr = new int[n][n];
         int count = 1; //矩阵中需要填写的数字
         int loop = 1; //循环的次数
         int startx = 0,starty = 0;
         int offset = 1; //偏移量
         int i,j;

         while(loop <= n/2){
            for(j = starty;j<n-offset;j++){
                arr[startx][j] = count++;
            }
             for(i = startx;i<n-offset;i++){
                arr[i][j] = count++;
            }
             for(;j>starty;j--){
                arr[i][j] = count++;
            }
             for(;i>startx;i--){
                arr[i][j] = count++;
            }

            startx++;
            starty++;
            loop++;
            offset++;
         }

		//中间最后一圈的时候的处理
         if(n%2==1){
            arr[startx][starty] = count;
         }
        
        return arr;
    }
}

58 区间和

​ 给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。

​ 输入描述

​ 第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间,直至文件结束。

​ 输出描述

​ 输出每个指定区间内元素的总和。

思路:前缀和。前缀和的思想是重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数。

public class PreAdd {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        //整数数组的长度
        int n = input.nextInt();
        int[] vec = new int[n];
        int[] preAdd = new int[n];

        int preSum = 0; //前缀和
        for (int i = 0; i < n; i++) {
            vec[i] = input.nextInt();
            preSum += vec[i];
            preAdd[i] = preSum;
        }

        while (input.hasNextInt()) {
            int intervalStart = input.nextInt(); //第一个区间
            int intervalEnd = input.nextInt(); //第二个区间

            int sum;
            if (intervalStart == 0) {
                sum = preAdd[intervalEnd];
            } else {
                sum = preAdd[intervalEnd] - preAdd[intervalStart - 1];
            }
            System.out.println(sum);
        }

        input.close();
    }
}

44 开发商购买土地

​ 在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。

​ 现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。

​ 然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。

​ 为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。

​ 注意:区块不可再分。

​ 输入描述

​ 第一行输入两个正整数,代表 n 和 m。

​ 接下来的 n 行,每行输出 m 个正整数。

​ 输出描述

​ 请输出一个整数,代表两个子区域内土地总价值之间的最小差距。

​ 输入示例

​ 3 3 1 2 3 2 1 3 1 2 3

​ 输出示例

​ 0

public class DeveloperLord {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        //n*m个连续的区块
        int n = input.nextInt(); //行
        int m = input.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] = input.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 i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                vertical[i] +=vec[j][i];
            }
        }

        //初始化结果变量为最大整数值,用于后续更新为最小值
        int result = Integer.MAX_VALUE;
        int horizaontalCut = 0; //横向切割线左侧的面积和
        for (int i = 0; i < n; i++) {
            horizaontalCut += horizontal[i];
            result = Math.min(result,Math.abs(sum-2*horizaontalCut));

        }

        int verticalCut = 0; // 纵向切割线左侧的面积和  
        for (int i = 0; i < m; i++) {
            verticalCut += vertical[i];
            result = Math.min(result,Math.abs(sum-2*verticalCut));
        }

        System.out.println(result);
    }
}
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值