刷题系列之977. 有序数组的平方

21 阅读2分钟

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

题目来源

leetcode.cn/problems/sq…

题目介绍

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

题目分析

根据题目首先要理解需要做的是啥,找出关键点。

1.已知非递减顺序整数数组nums。

2.返回一个新数组。

3.新数组元素根据nums里的每个元素的平方组成。

4.新数组要按非递减顺序排序。

综上所述,我们应该有一个新数组变量,用来存放nums数组平方后的元素,第二步将他们做个升序排序。

题目解答

一般解法

这种确实相对低效,当然也是最好理解的,虽然也能得出正确结果,不过循环太多了,主要就是利用了冒泡排序。

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let n = nums.length;
    let newNums = new Array(n).fill(0);
    for(let i=0;i<n;i++){
        newNums[i]=nums[i]*nums[i]
    }

     for(let i=0;i<n;i++){
        for (j = 0; j < n - i; j++) {
             //根据数组长度以及i的值定义内循环次数,每次比较两个数的大小
                    if (newNums[j] > newNums[j + 1]) {
                        let temp=newNums[j]
                        newNums[j]=newNums[j+1]
                        newNums[j+1]=temp
                    }       
         }        
      
    }
    
    return newNums;
};

双指针解法

一说到双指针就知道应该是从数组首尾开始比较。

这里我们用一个K表示新数组的下标,并且初始值设置为最大下标,用来为其赋值,这个解法就是在一个循环里把新数组排序好在输出。

数组从左下标 跟右下标比较开始,分别求出左边下标和右边下标元素的平方,因为不能递减,我们这里按递增处理,所以要比较大小。

如果平方后left<right,那么将right赋值给新数组最大下标k,然后让k-1,同时right往右移动一个值。

如果平方后left<right,那么left赋值给新数组下标为k的元素,同时left往前移动一个值。

这样可以保证新数组的顺序肯定是按升序来的。


/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let n = nums.length;
    let newNums = new Array(n).fill(0);
    let i = 0, j = n - 1, k = n - 1;
    while (i <= j) {
        let left = nums[i] * nums[i],
            right = nums[j] * nums[j];
        if (left < right) {
            newNums[k--] = right;
            j--;
        } else {
            newNums[k--] = left;
            i++;
        }
    }
    
    return newNums;
};

image.png

官方解答

我们可以使用两个指针分别指向位置 00 和 n-1n−1,每次比较两个指针对应的数,选择较大的那个逆序放入答案并移动指针。

思路是一样的,不过我们用了while循环,这里用for循环,其实本质一样。

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

总结

再一次见证了双指针解法解答数组类题目,真的很实用,双指针解法解决数组类算法题必须要掌握。