【java】刷算法--Array--有序数组的平方

98 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

题目

  • 分类:数组
  • 难度(入门|中等|难):入门
  • LeetCode链接

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

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

思路

  1. 理解要求: 非递减数组 --> 要求数组的后一个元素值大于等于前一个元素 --> 元素从小到大排序, 可以值重复的数组

  2. 难点: 由于存在负数值, 平方后大小顺序会打乱. 但打乱也不是全无规律

  3. 找规律:

    • 在上述给出的例子中, 找到绝对值最小的元素值, 也就是0,
    • 0以前的元素如果按绝对值排序, 是从大到小的有序序列
    • 0以后的元素序列是从小到大的有序序列
  4. 解题要点:

    • 本题的要求变为: 将两个有序序列, 组合为一个新的有序序列, 从小到大排序
    • 借助两个指针, 一个指针从前往后走, 另一个指针从后往前走. 相当于分别按从大到小的顺序遍历了两个有序数组.
    • 两个指针所指向的值相互比较, 将较大的插入新数组, 并且指针挪动, 另一个指针不动, 进入下一轮比较
    • 不断遍历比较, 临界点为两指针相遇, 完成比较.
  5. 难点:

    • 思路不好捋顺, 一旦理顺就演变为两个有序数组组合为新有序数组的问题.
    • 临界点判断: 当两个指针相遇时, 共同指向的那个值的插入.

代码

 class Solution {
     public int[] sortedSquares(int[] nums) {
         int[] newNums = new int[nums.length];
         int front = 0;
         int end = nums.length-1;
         int count = end;
         while(front<=end){
             int multif = nums[front]*nums[front];
             int multie = nums[end]*nums[end];
             if(multif>multie){
                 newNums[count] = multif;
                 front++;
             } else{
                 newNums[count] = multie;
                 end--;
             }
             count--;
         } 
         return newNums;
     }
 }

代码要点:

  • count这个变量表示新数组要插入元素的位置的索引. 从数组最后往前插入.
  • while(front<=end), 里面的等号如何确定加不加?

    • 这就是临界条件, 加不加的依据是: 当两指针相等时, 共同指向最后这个待加入的元素, while的大括号后面的代码能否实现最后这个元素的插入? 如果不行, 就得在外面额外插入最后一个元素.
    • 脑内模拟一下, 如果while里等号加上, 共同指向同一个元素时, 大括号内, multifmultie的值相等, 进入else判断, 如果最后一个元素能成功赋值, 就得要count值此刻等于0, 而count从nums.length-1开始, 每插入一个元素就count--, 挪动到下一个待插入元素的位置, 此时还剩一个元素没插入, count指向最后一个待插入的位置, 也就是count=0, 满足要求, 能插入.

总结

  • 如果题目有隐含数组遍历的要求, 那么就可以考虑双指针方法
  • 这道题从看似无序到有序, 转折点就是要分清有序数组在哪儿. 所以能找出题目的原型很重要.