首页 > 其他分享 >刷刷刷Day2| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

刷刷刷Day2| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

时间:2022-12-30 21:11:41浏览次数:70  
标签:977 nums int II ++ result 数组 指针

977.有序数组的平方

LeetCode题目要求

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

解题思路

由于给定的数组是有序且非递减(递增),而元素可能为负数,所以需要再平方后再排序

  • 思路1,先平方,再进行排序
class Solution {
    public int[] sortedSquares(int[] nums) {
        // 有序数组,非递减(递增),可能存在负数,平方后不一定是有序,因此需要再排序
        for (int i = 0; i < nums.length; i++) {
            int t = nums[i];
            nums[i] = t * t;
        }
        // 使用 Arrays.sort(int[]) 进行自然顺序排序
        Arrays.sort(nums);
        return nums;
    }
}
  • 思路2,双指针
class Solution {
    public int[] sortedSquares(int[] nums) {
        // 双指针怎么解决呢 
        // 输入:nums = [-4,-1,0,3,10]
        // 输出:[0,1,9,16,100]
        // 思路:遍历数组,做平方操作,平方后,如果值比后面的大,就与后面的交换
        int left = 0; // 左指针
        int right = nums.length - 1; // 右指针
        int[] result = new int[nums.length]; // 存储平方排序后的结果
        int k = right; // k 与 right 相等,从 k 位置开始放值
        while (left <= right) {
             //如果左指针平方 小于 右指针平方值,那么将大的值,放到 result k 的位置
            if (nums[left] * nums[left] < nums[right] * nums[right]) {
                result[k--] = nums[right] * nums[right];
                right--;
            } else {
                result[k--] = nums[left] * nums[left];
                left++;
            }
        }
        return result;
    }
}
重难点

双指针是个巧妙的解法,而且通过一个循环+指针移动就完成了。需要主要的点是:

  • while(left<=right) 这里使用的 <=, 需要和 right 的取值对应。
  • 指针移动,通过对比平方值,大的往右放,小的放左边

附:学习资料链接

209.长度最小的子数组

LeetCode题目要求

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
 示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

解题思路
  • 双指针,通过两个指针的移动,指针对应的值相加如果与 target 相等,记录两个指针间的长度。
    这个解法在 LeetCode 上跑居然超时了, 之前可以正常执行,很神奇
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int i = 0;
        int j = 0;
        int len = nums.length;
        int result = Integer.MAX_VALUE;

        /* 分析过程
        0   1   2   3   4   5
        2,  3,  1,  2,  4,  3
        i   j                  2+3=5 < 7   下一次移动 j
        i       j              2+3+1=6 < 7 这里移动 j
        i           j          2+3+1+2=8>7 下一次移动 i
            i       j          3+1+2=6 < 7 这里移动 i
            i           j      3+1+2+4=10 > 7 下一次移动 i
                i       j      1+2+4=7  下一次移动i,与 target 相等,记录 j-i+1 = 4-2+1 = 3
                    i   j      2+4=6 < 7 这里移动 i,下一次移动 j
                    i       j  2+4+3=9 > 7  这里移动 j,下一次移动 i
                        i   j  4+3=7 这里移动 i,与 target 相等,  记录 j-i+1= 5-4+1 = 2, 比前值小,返回
        */

        while(i <= j && j < len) {
            int sum = calc(nums, i, j);
            if (sum >= target) {
                int l = j - i + 1;
                result = l < result ? l : result;
                i++;
            } else if (sum < target) {
                j++;
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }

    private int calc(int[] nums, int i, int j) {
        int sum = 0;
        for(; i <= j; i++) {
            sum += nums[i];
        }
        return sum;
    }
}
  • carl 解法,滑动窗口
class Solution {

    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        // 遍历数组,过程中通过 left 与 right 指针形成一个滑动的窗口
        for (int right = 0; right < nums.length; right++) {
            // right 指针计算 每个滑动过的值的和
            sum += nums[right];
            // 如果滑动过的所有元素的和 大于等于 target ,那么就找到了
            while (sum >= target) {
                // 判断上一次的 result(窗口大小) 与当前窗口大小相比,取小的
                result = Math.min(result, right - left + 1);
                // 重新计算窗口内的和,但此时的操作是 将 left 指针右移,并且 sum 中把 left 指针的值减去,下一次再判断是否大于等于 target。
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
重难点

需要理解滑动窗口的思想:与双指针类似,通过两个指针形成一个窗口,然后通过移动左右指针,变换窗口的大小,形成与目标值匹配的大小

附:学习资料链接

59.螺旋矩阵II

LeetCode题目要求

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

解题思路

根据题目,需要输出的是一个 int[n][n] 的二位数组,那么输出时需要模拟成一个顺时针的螺旋,输出方式为 从左到右 --> 从上到下 --> 从右到左 --> 从下到上,如此重复,直到输出为 n/2 圈;
代码实现

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] result = new int[n][n];
        int startX = 0, startY = 0; // 每循环一圈的起始位置
        int loop = 0; //控制循环次数
        int mid = n / 2; // 矩阵中间位置
        int count = 1; // 填充数值
        int offset = 1; // 控制每个边遍历的长度,每次循环右边界收缩一位
        int i, j;
        
        while (loop++ < n / 2) { // 螺旋次数
            i = startX;
            j = startY;
            // 从左到右 左闭右开
            for (j = startY; j < n - offset; j++) {
                result[startX][j] = count++;
            }
            // 从上倒下 上闭下开
            for (i = startX; i < n - offset; i++) {
                result[i][j] = count++;
            }
            // 从右到左 右闭左开
            for (; j > startY; j--) {
                result[i][j] = count++;
            }
            // 从下到上 下闭上开
            for (; i > startX; i--) {
                result[i][j] = count++;
            }
            
            startX++;
            startY++;
            offset++;
        }

        if (n % 2 == 1) {
            result[mid][mid] = count;
        }

        return result;
    }
}
重难点
  • 确定好边界条件,需要注意的就是输出时,始终保持的是 闭开 原则,从开始到结束的形式为:左闭右开-> 上闭下开-> 右闭左开 -> 下闭上开
  • 如果 n 是奇数时,要对中间的点进行补充输出,才是完整的
    附:学习资料链接

标签:977,nums,int,II,++,result,数组,指针
From: https://www.cnblogs.com/blacksonny/p/17014678.html

相关文章

  • 数组数据类型
     代码示例:<!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title></head><body><script>var......
  • 【LeetCode数组#3有序数组的平方】有序数组平方
    有序数组的平方力扣题目链接(opensnewwindow)给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例1:输入:num......
  • 数组——多维数组、Arrays类讲解
    数组——多维数组、Arrays类讲解多维数组多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。二维数组inta[][]=newi......
  • js获取数组最后一个元素的方法
    //定义一个数组letarr=[10,20,30,40]//不会修改到原数组arr.slice(-1)[0]//40=>arr.slice(-1)返回的是数组arr.at(-1)//40=>支持传入一个下标,支持负......
  • 第三章《数组与循环》第8节:数组与循环经典例题
    利用数组和循环可以解决很多经典问题,比如对数字的查找、排列、筛选等。本小节甄选了其中一些有代表性的问题集中进行讲解,认真学习这些经典例题不仅有助于巩固Java语言的相关......
  • 迭代(遍历数组)forEach
    1.forEach用法vararr=[13,2,2,5] varsum=0 //forEach用法:Array.forEach(function(数组当前项的值,数组当前项的索引值,数组本身){}) arr.forEach(function(valu......
  • 稀疏数组
    1.先看实际需求编写的五子棋程序中,在存盘退出和续上盘的功能分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据,那么该怎么解决呢?稀疏数组。2.基......
  • leetcode-557. 反转字符串中的单词 III
    557.反转字符串中的单词III-力扣(Leetcode)与代码[[leetcode-541.反转字符串II]]相关联,swapStrBytes函数,使用了上次的代码funcreverseWords(sstring)string{......
  • 基于Python Numpy的数组array和矩阵matrix详解
    NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(通常是元素是数字)。在NumPy中维度(dimensions)叫做轴(axes)......
  • 把文件里的数据变成shell脚本中的数组
    阿斯蒂芬filelist=$(cat/opt/fossx/data/wyyshell/norma.txt)数组的定义格式是有强制规范的:(item item item ...),注意是两个空格;赋值号=两边不能有空格,必须紧挨......