JS|数组sort()方法排序错乱的原因及解决方法

165 阅读2分钟

一、发现问题

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]

直观思路:

先将nums各元素平方,再排序。

错误解答如下:

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let arr=[];
    for(i=0;i<nums.length;i++){
        arr[i]=nums[i]*nums[i];
    }
    arr.sort();
    return arr
};

测试用例:

输入:nums=[-4,-1,0,3,10]

输出:[0,1,100,16,9]

预期结果:[0,1,9,16,100]

发现100排在16的前面,sort()方法排序错乱。

二、问题原因

MDN文档中解释:

sort()  方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的。

在比较数字大小时,会逐个比较,因此“100”会排在“16”前面。

三、解决办法

1.将比较函数作为参数传给sort()

function compare (val1,val2){
    if(val1 < val2){
        return -1
    }else if(val1 > val2){
        return 1
    }else{
        return 0;
    }
}

var arr=[16,1,0,9,100]
console.log("排序前的数组",arr) //排序前的数组  [16, 1, 0, 9, 100]
arr.sort(compare);
console.log("排序后的数组",arr) //排序后的数组  [0, 1, 9, 16, 100]

2.将比较函数简化为箭头函数

var arr=[16,1,0,9,100]
console.log("排序前的数组",arr) //排序前的数组  [16, 1, 0, 9, 100]
arr.sort((val1,val2)=>val1>val2?1:val1<val2?-1:0);
console.log("排序后的数组",arr) //排序后的数组  [0, 1, 9, 16, 100]

3.若数组元素是数值,或是valueof()方法返回数值的对象(如Date对象),可进一步简化。

var arr=[16,1,0,9,100]
console.log("排序前的数组",arr) //排序前的数组  [16, 1, 0, 9, 100]
arr.sort((val1,val2)=>{return val1-val2;});
console.log("排序后的数组",arr) //排序后的数组  [0, 1, 9, 16, 100]