代码随想录训练营Day2|Leetcode 977.有序数组的平方 Leetcode 209.长度最小的子数组 Leetcode 209.长度最小的子数组 Leetcode 59.螺旋矩阵II

Leetcode  977.有序数组的平方

双指针(头尾两端指针值作比较)

思路:平方后最大数不是在左边就是在右边,所以可以引用双指针从数组两端开始比较,比较、并向中间移动对应的指针

问题: for(i=0,j=nums.Length-1;i<=j; )这个循环条件过了一段时间重刷直接乱写写了个while(i<=j)……就是注意这个循环条件+每次比较出头一个和最后一个中更大的那个存储到结果数组末端(因为要升序排列)

public class Solution {
    public int[] SortedSquares(int[] nums) {
        int[] result=new int[nums.Length];
        int k=nums.Length-1;
        int i,j;
        for(i=0,j=nums.Length-1;i<=j; ){
            if(nums[i]*nums[i]>nums[j]*nums[j]){
                result[k]=nums[i]*nums[i];
                k--;
                i++;
            }else{
                result[k]=nums[j]*nums[j];
                k--;
                j--;
            }
        }
        return result;
    }
}

 209.长度最小的子数组

示例一:暴力解法

暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

public class Solution {
    public int MinSubArrayLen(int target, int[] nums) {
         int result = int.MaxValue; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.Length; i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.Length; j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= target) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == int.MaxValue ? 0 : result;
    }
}

示例二:滑动窗口

滑动窗口(可以理解为特殊的双指针,窗口大小和起始位置会变化)

思路:滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。l两个指针,一个表示窗口起始位置、一个表示窗口终止位置。

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

记忆:

1.最大整型值int.MaxValue。

2.for循环条件移动结束位置,循环体内移动开始位置。

3.移动开始位置前需要把原本开始位置的值减去再移动

public class Solution {
    public int MinSubArrayLen(int target, int[] nums) {
        int result=int.MaxValue;//初始化为最大值
        int sum=0;
        int subLen=0;
        int i=0;
        for(int j=0;j<nums.Length;j++){
            sum+=nums[j];
            while(sum>=target){
                subLen=j-i+1;
                result=result<subLen?result:subLen;//判断新的区间是不是比已知最小区间小,如果是的话就更新区间长度
                sum-=nums[i];//需要移动滑动窗口左边指针了,所以相应的要把左边指针原本指向的值减去,再判断减去后条件是否仍然成立
                i++;//移动左边指针
            }
        }
        return result==int.MaxValue?0:result;//最后结果判断,如果得到了有效的结果值就返回结果值,否则返回0
    }
}

Leetcode 59.螺旋矩阵II

思路:

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

注意点:遍历条件,左右边界的开闭要一致,边界的值要清晰

以左闭右开为例

图片来源:代码随想录代码随想录 (programmercarl.com)

记忆:

1.C#二位数组初始化

  1. int[][] answer = new int[n][];:这一步创建了一个长度为 n 的一维数组,每个元素都是一个整型数组的引用。但此时内部的每个整型数组并未初始化,它们仅仅是空引用。

  2. answer[i] = new int[n];:这个语句初始化了每个一维数组,并使其成为长度为 n 的整型数组。通过循环遍历 n 次,为每个一维数组分配了新的大小为 n 的整型数组。

        int[][] answer = new int[n][];
        for(int i = 0; i < n; i++)
            answer[i] = new int[n]; 

 思路一:定义上下左右边界,根据图示的螺旋进行数值填充(螺旋矩阵I也可以用这种思路解)

public class Solution {
    public int[][] GenerateMatrix(int n) {
        //初始化
       int[][] array=new int[n][];
       for(int i=0;i<n;i++){
        array[i]=new int[n];
       }
        //边界
        int top=0;
        int bottom=n-1;
        int left=0;
        int right=n-1;
        int num=0;
        while(num<n*n){
            //从左到右
            for(int i=left;i<=right;i++){
                array[top][i]=++num;
            }
            top++;
            //从上到下
            for(int i=top;i<=bottom;i++){
                array[i][right]=++num;
            }
            right--;
            //从右到左
            for(int i=right;i>=left;i--){
                array[bottom][i]=++num;
            }
            bottom--;
            //从下到上
            for(int i=bottom;i>=top;i--){
                array[i][left]=++num;
            }
            left++;
        }
    return array;
}
}

思路二:使用起始和结束边界值,在一圈赋值结束后缩小边界范围,并且单独处理n为奇数的情况。代码更简洁

public class Solution {
    public int[][] GenerateMatrix(int n) {
        // 初始化一个 n x n 的二维数组作为结果矩阵
        int[][] answer = new int[n][];  // 创建一个长度为 n 的一维数组,每个元素是整型数组的引用
        for (int i = 0; i < n; i++)
            answer[i] = new int[n];  // 为每个一维数组分配一个长度为 n 的新整型数组

        int start = 0;  // 螺旋矩阵的起始行索引
        int end = n - 1;  // 螺旋矩阵的结束行索引
        int tmp = 1;  // 待填充的数值,从 1 开始递增

        // 按顺时针螺旋顺序填充矩阵
        while (tmp < n * n) {
            // 填充上行
            for (int i = start; i < end; i++)
                answer[start][i] = tmp++;

            // 填充右列
            for (int i = start; i < end; i++)
                answer[i][end] = tmp++;

            // 填充下行
            for (int i = end; i > start; i--)
                answer[end][i] = tmp++;

            // 填充左列
            for (int i = end; i > start; i--)
                answer[i][start] = tmp++;

            start++;
            end--;
        }

        // 处理奇数阶情况中心点
        if (n % 2 == 1)
            answer[n / 2][n / 2] = tmp;

        return answer;  // 返回生成的螺旋矩阵
    }
}

两种思路的区别:

在第二种代码中的螺旋填充算法中,不需要额外考虑 n 是否为奇数的情况,因为该算法可以适用于任何正整数 n。在循环过程中,通过调整边界并按照规定的顺序填充数字,最终能够正确生成螺旋排列的矩阵,无论 n 是奇数还是偶数。

在第二种算法中,由于我们是从外向内依次填充矩阵,最后会自然地填充到中心点,而不需要特殊处理。即使 n 为奇数,也能够正确地填充完整个矩阵。这种算法设计避免了在循环中针对奇数情况进行额外操作。

前一种方法需要考虑奇数和偶数情况,因为那种方法是基于设定了起始点和结束点,需要根据 n 的奇偶性来分别处理中心点的填充。而现在这种方法通过固定四个边界的方式,能够统一处理各种 n 的情况,使得中心点的填充变得更加简单且自然。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值