代码随想录day02| 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II

目录

977  有序数组的平方

209  长度最小的子数组

59  螺旋矩阵 II


977  有序数组的平方

题目链接

代码随想录题解

看到题目的第一想法:这道题之前有遇到过,第一思路是判断数组是否是全为正数或者全为负数,对上面这两种情况单独处理;如果数组既包含正数也包含负数,就找到第一个出现的正数,而后拿两个指针分别向左右移动,但是这块的处理上一直无法ac,后面在仔细研究一下。

看完代码随想录之后的想法:卡哥的方法清晰明了~

代码实现:

我的思路:

  • 对于有break的for循环,当break的时候,后面那次i++是不执行的;所以处理后面的循环时i+1;
  • 当一侧到边界的时候,另一侧肯定未到边界,比如左侧已越界,需要right < length写到判断条件上,防止越界异常;
class Solution {
    public int[] sortedSquares(int[] nums) {
        //有思路,但是查找了第一个正数,而后代码写的也无法通过。。看到卡哥的写法,茅塞顿开,原来这么简单。。
        //o(n)的时间复杂度,要使用双指针才行
        int length = nums.length;
        if(length == 0) {
            return new int[0];
        }
        int[] result = new int[length];
        if (length > 0 && nums[length - 1] <= 0) {
            for (int i = 0; i < length; i++){
                result[i] = nums[length - 1 - i] * nums[length - 1 - i];
            }
            return result;
        }
        if (length > 0 && nums[0] >= 0) {
            for (int i = 0; i < length; i++){
                result[i] = nums[i] * nums[i];
            }
            return result;
        }
        //寻找第一个正数
        int index = 0;
        for(int i = 0; i < length; i++) {
            if(nums[i] >= 0) {
                index = i;
                break;
            }
        }
        //此时index必然>=1
        int left = index - 1;
        int right = index;
        int i = 0;
        for(; i < length; i++){
            if (nums[left] * nums[left] <= nums[right] * nums[right]) {
                result[i] = nums[left] * nums[left];
                left--;
                if(left < 0){
                    //到边界即跳出
                    break;
                }
            }else {
                result[i] = nums[right] * nums[right];
                right++;
                if(right >= length){
                    //到边界即跳出
                    break;
                }
            }

        }
        //当一侧到边界的时候,另一侧肯定未到边界,比如左侧已越界,需要right < length写到判断条件上,防止越界异常
        //此情况是左侧到边界,而右侧未到
        if(left == -1 && right < length) {
            //对于有break的for循环,当break的时候,后面那次i++是不执行的;所以处理后面的循环时i+1;
            for (i = i + 1; i < length; i++) {
                result[i] = nums[right] * nums[right];
                right++;
            }
        }
        //此情况为右侧到边界,而左侧未到
        if(right == length && left >= 0) {
            for (i = i + 1; i < length; i++) {
                result[i] = nums[left] * nums[left];
                left--;
            }
        }
        return result;
    }
}

代码随想录提供的方法:

class Solution {
    public int[] sortedSquares(int[] nums) {
        int length = nums.length;
        int l = 0;
        int r = length - 1;
        int[] result = new int[length];
        int index = length - 1;
        while (l <= r) {
            if (nums[l] * nums[l] <= nums[r] * nums[r]) {
                result[index--] = nums[r] * nums[r];
                r--;
            }else {
                result[index--] = nums[l] * nums[l];
                l++;
            }
        }
        return result;
    }
}

实现过程中遇到哪些困难:

  • 寻找到第一个正数后,如果对元素的平方进行排序 ?
    • 相关部分代码见上方我的思路

209  长度最小的子数组

题目链接

代码随想录题解

看到题目的第一想法:这题之前刷过,知道要用华东窗口来处理,但是具体的实现上总是有些问题,题目很难ac。

  • 以下面这块为例,只对sum >= target 进行处理即可,而我最开始外面使用的是while循环,条件为fast < length,但是这么写总也无法ac,现在也没有想通,后续再看看,已处理~
  • 问题出在了下面两个语句的顺序上,开始是将if语句放在前面,while语句放在后面,这样就会有问题,比如fast未进行自增时,就可能出现sum>=target的情况,这样就有数据的丢失,将while语句放在if语句之前即可~
        //for (;fast < length;fast++) {
        while(fast < length) {
            sum += nums[fast];

            if(sum < target) {
                fast++;
            }

            while (sum >= target && slow <= fast) {
                result = Math.min(result, fast - slow + 1);
                sum -= nums[slow++];
            }
        }

看完代码随想录之后的想法:单独对特殊情况处理即可,有的不需要处理。想明白之后再开始写代码!

代码实现:

  • 代码随想录提供的解法中,result = Integer.MAX_VALUE;而在返回时,若是result未被赋新值就说明方法中没有符合条件的子数组,按题意返回0,否则返回被赋值的result
    result == Integer.MAX_VALUE ? 0 : result
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //滑动窗口
        int length = nums.length;
        int fast = 0, slow = 0;
        int result = length;
        int sum = 0;
        for (int i = 0; i < length; i++) {
            sum += nums[i];
        }
        if(sum < target) {
            return 0;
        }
        sum = 0;
        for (;fast < length;fast++) {
        //while(fast < length) {
            sum += nums[fast];
            while(sum >= target) {
                result = Math.min(result, fast - slow + 1);
                sum -= nums[slow++];
            }
            /*if(sum < target) {
                fast++;
            }
            while (sum >= target && slow <= fast) {
                result = Math.min(result, fast - slow + 1);
                sum -= nums[slow++];
            }*/
        }
        return result;
    }
}

实现过程中遇到哪些困难:

  • while循环与for循环使用上还有不少的问题:
    • while循环的使用依旧不是很熟练,结束条件的判定也不准确。

59  螺旋矩阵 II

题目链接

代码随想录题解

看到题目的第一想法:这也是一道刷过的题,有大致的思路,但是写的时候却是无从下手。

看完代码随想录之后的想法:此题也涉及到了循环不变量,以每条边而言,都是前闭后开进行处理的。

代码实现:

class Solution {
    public int[][] generateMatrix(int n) {
        //之前做个这个题,有点简单的思路,但是还是有无从下手的感觉
        int circle = 0;
        int start = 0;
        int i,j;//i为行数,j为列数
        int count = 1;
        //创建数组,用以存放结果
        int[][] result = new int[n][n];
        while (circle++ < n / 2) {
            //循环不变量,前闭后开区间
            //上层从左到右
            for(j = start; j < n - circle; j++) {
                result[start][j] = count++;
            }
            //右侧从上到下
            for(i = start; i < n - circle; i++) {
                result[i][j] = count++;
            }
            //下层从右到左
            for (; j >= circle; j--) {
                result[i][j] = count++;
            }
            //左侧从下到上
            for (; i >= circle; i--) {
                result[i][j] = count++;
            }
            start++;
        }
        if (n % 2 == 1){
            result[start][start] = count;
        }
        return result;
    }
}

实现过程中遇到哪些困难:

  • 循环圈数的确定,为什么要用circle++?
    • 以n=3为例,只需要一层循环即可,即为n/2,circle++则是用来方便处理下面代码中的边界问题,
  • start的作用?
    • 最开始为 i,j 赋值,相当于圈数-1,方便单独对中心(n为奇数时)的元素进行赋值

今日收获,记录一下自己的学习时长

  • 算法处理约3h,博客编写约2h
  • 熟悉了双指针法、滑动窗口与模拟行为与双指针法,编写博客也是对自己思路的梳理~
  • 贵在坚持,加油!

 数组总结:

  • 数组元素不能被删除,只能被覆盖;
  • Java中二维数组的地址空间是不连续的,以int[3][4]为例,其由四个连续的地址控件组成,分别为1个能执行其他3个地址的空间,和其他3个长度为4的连续空间,so 1+3~

 

  • 数组相关的算法有:二分法(循环不变量),双指针法(快慢指针降低一级时间复杂度),滑动窗口(两指针动态变化),模拟行为(行为的模拟+循环不变量)等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值