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