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

Leetcode 977.有序数组的平方

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

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

思路 1:暴力解法

将每个数都平方后再进行排序

思路二:双指针法

前提:数组是升序排列

 双指针的动态图q

因为有负数和正数所以在比较时候首先会考虑用绝对值,这样的话每个数字都要进行判断正负显然不是好办法,所以用绝对值来比较更方便(此题刚好是平方的排序更加方便)。

创建一个结果数组指针每移动一次就可以将一个数字放入结果的数组中

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

 

Leetcode209. 长度最小的子数组 

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0

 

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

思路一:暴力解法(Leetcode无法通过)

双层for循环将长度记录下来然后再挑选最小的一个数字

这个是我自己写的

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //滑动窗口
        int k = 0;//用k来记录最子数组的长度
        int i = 0, j = 0;
        int t = 0;//用来计算每一个窗口内的数据和
        int m = 0;//内层循环达到目标数时就及时停止
        int[] n = new int[nums.length];//记录子串长度
        for(i = 0; i < nums.length;i++ ){    //双层循环找出对应长度
            for(j = i;(j < nums.length) && (m == 0); j++){    //m作用就是在达到target后及
                t = t + nums[j];//累加                        //时停止   
                k++;
                if(t >= target){
                    m = 1;
                    n[i] = k;
                }
            }
            if(k==1){        //最短长度为1所以有1直接停止
               i++; 
               break;
            }
            if((k == nums.length - i + 1) && (t < target)){
                i++;               
                n[i] = 0;        //如果符合条件说明后面数之和已经达不到target及时结束
                break; 
            }
            t = 0;               //每次内层循环结束要将一些变量刷新 
            k = 0;
            m = 0;
        }

          t = n[0];        //如果第一个数等于零说明所有数加起来都达不到target不用进入循环
          for(i = 0; (i < nums.length) && (t != 0); i++){    
            if(t >= n[i] && n[i] != 0){    //在循环中找非零且最小的数
                t = n[i];
            }
        }
        return t;
    }
}

 这个可以更简单一点设置一个最大长度length = Integer.MAX_VALUE,每次进行替换就不用数组了

Integer.MAX_VALUE的做法在这

思路二:滑动窗口 

这道题目非常的经典,我开始想到用滑动窗口但用成了暴力解法,原因都在这条视频中:

滑动窗口讲解

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //滑动窗口
        int i = 0,j = 0;
        int sum = 0;
        int length = nums.length;
        int flag = 0;
        for(j = 0; j < nums.length; j++){
            sum = sum + nums[j];
            while(sum >= target){
                if(length > j - i + 1){
                    length = j - i + 1;
                }
                flag = 1;
                sum = sum - nums[i++];
            }
        }
        if(flag == 0){   //代码下有为什么做标记的解释
            length = 0;
        }
        return length;
    }
}

 我开始定义length = nums.length 所以在最后它会有两种情况

1.如果刚好所有数加起来能达到target,所以它的长度不变

2.它所有数加起来达不到target,没有进行长度交换,出来的长度仍然不变

为了解决这个问题就增加标记位,如果达到target,'flag'就会变化这样就将这个问题解决了。

还有用到Integer.MAX_VALUE的办法:代码

这里又回顾到 ? : 的用法 :

可以判断对错的式子 ? a : b,

如果式子正确则结果为a,如果结果错误结果为b.

还有就是Java中等号还与地址有关,如果两边是变量的话就是看地址是否相同

如果两边都被赋值后就是正常的数字赋值

Leetcode 59.螺旋矩阵 

题目:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 

n x n 正方形矩阵 matrix 。

示例 1:

 

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]] 

 这道题目如果思路不是那么清晰,这一块对上了下一块对不上推荐直接看视频:59.螺旋矩阵

 一进循环深似海,从此offer是路人

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] result = new int[n][n]; 
        int i = 0,j = 0;
        int count = 0;
        int offe = 1;
        for(int m = 0; m < n / 2; m++){
            for( ;j < n - offe; j++){
                result[i][j] = ++count;
            }
            for(; i< n - offe; i++){
                result[i][j] = ++count;
            }
            for( j = n - offe; j > offe - 1; j--){
                result[i][j] = ++count;
            }
            for( i = n - offe; i >  offe - 1; i--){
                result[i][j] = ++count;
            }
            i++;
            j++;
            offe++;
        }
        if(n % 2 == 1){
            result[n / 2][n / 2] = ++count;
        }
        return result;
    }
}

 这道题目的话我也是在看完视频后才做出来的,首先是对左闭右开左开右闭的选取,其实直接到矩阵中来可以看出是左闭右开,然后进行循环每次的范围在变所以得用offe这些视频都有......

主要说一下为啥 i++和j++:for(a; b; c) a是初始的一些东西,b是进入循环的条件,每次循环结束后c才开始工作,然后再经过b判断......这些都是知道的

但是每次到最后c工作后才结束比如for(i = 0; i < 10; i++){}最后出来i的值为10,回到上面的代码,依据上面的例子自己可以走一圈就会发现它每次结束后i == j 正好在对角(每一圈开始的位置),

然后 i++,j++,就直接到下一圈的开始。如果完整读完这一段后对于上面某个位置有疑惑可以留言进行讨论。

 总结:很多代码一看就会一写就费,所以要多练习;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值