[路飞]算法:最小的k个数

393 阅读2分钟

最小的k个数

正题

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:

输入: arr = [3,2,1], k = 2
输出: [1,2] 或者 [2,1]

示例 2:

输入: arr = [0,1,2,1], k = 1
输出: [0]

解析

这是一道leetcode简单题,找出最小的k个数最容易想到的方法就是从小到大排序,那么最小的k个数就是前K个元素。所以这一题从某方面讲其实考的是排序。

但在 js 中我们可以使用 sort函数进行排序,能最快解决问题,我们可以使用sort函数

排序法

 var getLeastNumbers = function(arr, k) {
     // 使用 sort 方法排序
     arr = arr.sort((a, b) => {
         return b - a
     })
     // arr 就是从小到大哦排序后的数组
     
     return arr.splice(arr.length - k) // 取得前 K 个元素组成的数组,就是k个最小数
 };

替换法

替换法比较繁琐,但也是解决问题的方法之一。

1.gif

//替换法
var getLeastNumbers = function(arr, k) {
    if (k === 0) {
        return []
    }
    const res = [arr[0]]
    for(let index = 1; index < arr.length ; index++) {
        if (res.length < k) {
            res.push(arr[index])
        } else {
            const max = Math.max(...res)
            if (arr[index] < max) {
                res[res.indexOf(max)] = arr[index]
            }
        }
    }
    return res
}

计数法

计数法的原理与计数排序是一样的,实际上就是用空间交换时间的一种算法,一句话总结计数法就是:原数组中的值就是新数组的下标

// 计数法
var getLeastNumbers = function(arr, k) {
    if (k === 0) {
        return []
    }
    const newArr = new Array(Math.max(...arr) + 1).fill(0) // 新数组
    for(let index = 0 ; index < arr.length ; index++) {
        newArr[arr[index]] += 1
    }
    const res = []
    for (let index = 0 ; index < newArr.length ; index++) {
        for (let j = 0 ; j < newArr[index] ; j++) {
            if (res.length === k) {
                break
            }
            res.push(index)
        }
        if (res.length === k) {
            break
        }
    }
   return res
}

image.png

可以看到计数法在空间上消耗非常大,但是在时间上还是有一定优势的。