Day2:(数组)977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵Ⅱ

977.有序数组的平方

  • 题目链接977.有序数组的平方
  • 解题思路
    • 暴力法:直接把每个数原地平方,然后排序整个数组,这种方法的时间复杂度是 O(n + nlogn)。
    • 双指针法:因为数组是有序的,平方后最大的元素一定在数组两侧而不会在数组的中间位置,因此可以设定两个指针从数组的头尾开始进行比较,并按大小顺序放进一个新的数组里,同时完成平方和排序的工作,这种方法的时间复杂度是O(n)。
  • 主要难点:双指针方法的运用。
  • 解题步骤
    • 设定头尾两个指针以及一个空的新数组,长度与原数组相同
    • 比较头尾指针对应元素平方的值,将大的数放进新数组的末尾,更新指针,如果的左边的大就左指针右移一位,如果右边大的话就右指针左移一位
    • 重复上述过程,直到左右指针相同时完成循环,返回新的数组即为所求。
  • 代码
class Solution {
    public int[] sortedSquares(int[] nums) {
        int l = 0;
        int r = nums.length-1;
        int[] result = new int[nums.length];
        int k = nums.length-1;
        while(l<=r) {
            if(nums[l]*nums[l]>nums[r]*nums[r]){
                result[k] = nums[l]*nums[l];
                k--;
                l++;
            }else{
                result[k] = nums[r]*nums[r];
                k--;
                r--;
            }
        }
        return result;
    }
}

209.长度最小的子数组

  • 题目链接209.长度最小的子数组
  • 解题思路
    • 暴力法:循环找到每一个满足题目要求的子数组并保存长度,最后比较大小选最短的一个,时间复杂度O(n²)
    • 滑动窗口法(和双指针差不多):设定一前一后两个指针,每当得到符合题目要求的数组时更新数组值,并向前移动滑动窗口。时间复杂度为O(n)。
  • 主要难点:滑动窗口的前移过程
  • 解题步骤
    • 设置左右指针初始为0,新建一个变量赋无穷大值,用来保存最终结果即最短的数组长度
    • 右指针开始向前移动,每移动一位判断当前滑动窗口内的和是否大于等于target
    • 若满足要求,则更新数组长度值,永远保存最小,同时数组和减去左指针对应的数,左指针右移一位。
    • 若不满足要求则右指针继续向右移动
    • 当右指针移到数组末尾,左指针完成所有移动后停止,输出最短数组长度变量值,若其仍为初始最大值则返回0.
  • 代码:
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for(int right = 0;right<nums.length;right++){
            sum += nums[right];
            while(sum>=target){
                //更新当前长度,取最短
                if(right - left + 1 < result){
                    result = right - left + 1;
                }
                sum -= nums[left];//把最前面的一位减掉
                left++;//左指针右移一位
            }
        }
        if(result == Integer.MAX_VALUE){
            return 0;
        }else{
            return result;
        }
    }
}

59.螺旋矩阵Ⅱ

  • 题目链接:59.螺旋矩阵Ⅱ
  • 解题思路:本题基本不涉及什么算法,主要是按照顺序填充矩阵,对循环判断的条件逻辑要求较高。类似前一天做的二分法,这道题也需要时刻满足循环不变量原则,即在填充的过程中坚持左闭右开或左开右闭,从外向内循环填充整个矩阵。
  • 主要难点:循环不变量原则的满足,每个部分填充的判断条件逻辑,以及n为奇数时手动填充中间位置的数值。
  • 解题步骤:
    • 新建矩阵,新建循环过程中需要用到的变量
    • 使用左闭右开规则进行填充,分别写四个方向的填充循环代码
    • 当n为奇数时,需要在最后手动填充矩阵最中央的数值
  • 代码:
class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int loop = 0;//循环次数
        int start = 0;//每次循环开始点
        int num = 1;//填充数字
        int i,j;
        //填充过程全部坚持左闭右开规则
        while(loop++<n/2) {
            //上侧左到右
            for(j=start;j<n-loop;j++){
                res[start][j]=num++;
            }
            //右侧上到下
            for(i=start;i<n-loop;i++){
                res[i][j]=num++;
            }
            //下侧右到左
            for(;j>=loop;j--){
                res[i][j]=num++;
            }
            //左侧下到上
            for(;i>=loop;i--){
                res[i][j]=num++;
            }
            start++;
        }
        //特别情况:当n为奇数时,需要手动填充矩阵最中央位置元素
        if(n%2==1){
            res[start][start]=num;
        }
        return res;
    }
}

总结

今天的三道题之前都有做过一遍,再拿来做的时候有思路但是写的过程还是容易出各种错误,这三道题的主要思想是双指针法和循环不变量原则,双指针法使用两个指针进行移动能够将两个for循环减少到一个for循环,提高程序的时间复杂度;循环不变量原则是写代码时的一种原则,通过固定的规则去编码能够减少循环判断条件的复杂度,让逻辑更加清晰。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值