LeetCode面试题:数组中的第K个最大元素(JavaScript)

215. 数组中的第K个最大元素(题目).

尝试了很多方法,主要是为了进行一个结果的对比。提交结果如下(从上到下):
堆排序:构造k个元素的小根堆
堆排序:构造nums.length个元素的大顶堆,使从小到大排序
堆排序:构造nums.length个元素的小根堆(一点bug忽略)
快速排序(优化):减少排序次序
快速排序
直接nums.sort():时间超过所有JS提交代码90%+(强,但是面试最好自己写排序image.png
方法1:直接nums.sort()

var findKthLargest = function(nums, k) {
  if(!nums.length) return -1
  return nums.sort((a, b) => (a-b))[nums.length-k]
};

方法2:快速排序

var findKthLargest = function(nums, k) {
    if(!nums.length) return -1
    let quickSort = function(arr, start, end) {
        if(start >= end) return
        let temp = arr[start]
        let i = start, j = end
        while(i<j) {
            while(i<j && temp <= arr[j]) j--
            arr[i] = arr[j]
            while(i<j && temp >= arr[i]) i++
            arr[j] = arr[i]
        }
        arr[i] = temp
    }
    quickSort(nums, 0, nums.length-1)
    return nums[nums.length-k]
};

时间复杂度 O(NlogN)
空间复杂度 O(1)

接下去对快排进行优化

方法3:快速排序(优化)
优化的点就是:在快排选择多个块同步进行排序的时候,添加判断标准,提早结束。
判断标准:判断当前确定的节点下标是否等于nums.length - k,等于则找到;大于则向后找,小于则往前找。减少排序负载。

var findKthLargest = function(nums, k) {
    if(!nums.length) return -1
    let key = nums.length - k
    let quickSort = function(arr, start, end) {
        if(start >= end) return
        let temp = arr[start]
        let i = start, j = end
        while(i<j) {
            while(i<j && temp <= arr[j]) j--
            arr[i] = arr[j]
            while(i<j && temp >= arr[i]) i++
            arr[j] = arr[i]
        }
        arr[i] = temp
        // 添加判断标准,提早结束(优化的地方)
        if(i === key) 
            return
        else if(i > key)
            quickSort(arr, start, i-1)
        else 
            quickSort(arr, i+1, end)
    }
    quickSort(nums, 0, nums.length-1)
    return nums[key]
};

方法4:堆排序
构造nums.length个元素的大顶堆(使从小到大排序)

var findKthLargest = function(nums, k) {
    if(!nums.length) return -1
    // 调堆
    let heapSort = function(arr, start, end) {
        let temp = arr[start]
        for(let j=2*start+1; j<=end; j=2*j+1) {
            if(j<end && arr[j] < arr[j+1]) j++
            if(temp > arr[j]) break
            arr[start] = arr[j]
            start = j
        }
        arr[start] = temp
    }
    let len = nums.length
    for(let i=Math.floor(len/2-1); i>=0; i--)
        heapSort(nums, i, len-1)
    for(let i=len-1; i>0; i--) {
        let temp = nums[0]
        nums[0] = nums[i]
        nums[i] = temp
        heapSort(nums, 0, i-1) 
    }
    return nums[len-k]
};

方法5:堆排序(优化)
构造k个元素的小根堆
创建一个为长度k的数组,并建立小根堆,逐个与堆外元素比较大小,若比小根堆根元素大就替换掉根元素,然后调整堆使堆顶元素最小。

var findKthLargest = function(nums, k) {
    if(!nums.length) return -1
    // 调堆过程
    let heapSort = function(arr, start, end) {
        let temp = arr[start]
        for(let j=2*start+1; j<=end; j=2*j+1) {
            if(j<end && arr[j] > arr[j+1]) j++
            if(temp < arr[j]) break
            arr[start] = arr[j]
            start = j
        }
        arr[start] = temp
    }
    // 创建一个为长度k的数组,并建立小根堆
    let numsArr = nums.slice(0, k)
    for(let i=Math.floor(k/2-1); i>=0; i--)
        heapSort(numsArr, i, k-1)
    // 逐个与堆外元素比较大小
    for(let i=k; i<nums.length; i++) {
        // 若比小根堆根元素大就替换掉根元素,然后调整堆使堆顶元素最小
        if(nums[i] > numsArr[0]) {
            numsArr[0] = nums[i]
            heapSort(numsArr, 0, k-1)
        }
    }
    return numsArr[0]
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值