topK(划分法、最大顶堆法)

1)划分法

/**
 思路:利用快速排序的原理,每次选取第left的值作为参考值:找出一个划分位置low,使得L[low],左边的值比参考值大,右边的值比参考值小,
    这样一直持续下去,直到low和K相等,则可以找到前K个最大值。因为选取每个参考值,都要遍历一遍数组,因此:算法复杂度为O(N)。
 */
function partition(L, left, right) {
    let low = left;
    if (left < right) {
        let key = L[left];
        let high = right;
        while (low < high) {
            while (low < high && L[high] <= key) {
                high -= 1;
            }

            L[low] = L[high];
            while (low < high && L[low] >= key) {
                low += 1;
            }

            L[high] = L[low];
        }

        L[low] = key;

        return low;
    }
}

function topK(L, k) {
    let low = 0;
    let high = L.length - 1;
    let j = partition(L, low, high);

    while (j != k && low < high) {
        if (k > j) {
            low += 1;
        }else{
            high = j;
        }
        j = partition(L, low, high);
    }
}

let L = [3,2,7,4,6,5,1,8,0, 19, 23, 4, 5, 23, 3, 4, 0,1,2,3,45,6,5,34,212,3234,234,3,4,4,3,43,43,343,34,34,343,43,2]
let n = 10;
topK(L, n);
console.log(L.slice(0, n));

/**
 [ 234, 3234, 343, 343, 212, 45, 43, 43, 34, 43 ]
 */

2)大顶堆法

/**
 思路:先用前K个值构建大顶堆,也就是顶部是最大值,如果下一个值比顶部大,则立马调整这个大顶堆,
      否则取叶子节点肯定是一个最小值,如果数组中值比最小值还小,则直接舍弃。 算法复杂度为O(N * log(N))
 */
function build_heap(lists, size) {
    let sz = Math.floor(size / 2);
    for (let i = sz - 1; i >= 0; i--) {
        adjust_heap(lists, i, size);
    }
}

function adjust_heap(lists, i, size) {
    let lchild = 2 * i + 1;
    let rchild = 2 * i + 2;
    let max = i;
    if (i < size / 2) {
        if (lchild < size && lists[lchild] > lists[max]) {
            max = lchild
        }

        if (rchild < size && lists[rchild] > lists[max]) {
            max = rchild;
        }

        if (max != i) {
            let temp = lists[max];
            lists[max] = lists[i];
            lists[i] = temp;
            adjust_heap(lists, max, size);
        }
    }
}

function heap_sort(lists) {
    let size = lists.length;
    build_heap(lists, size);
    for (let i = size - 1; i >= 0; i--) {
        let temp = lists[i];
        lists[i] = lists[0];
        lists[0] = temp;
        adjust_heap(lists, 0, i);
    }

    return lists;
}

let L = [3, 2, 7, 4, 6, 5, 1, 8, 0, 19, 23, 4, 5, 23, 3, 4, 0, 1, 2, 3, 45, 6, 5, 34, 212, 3234, 234, 3, 4, 4, 3, 43, 43, 343, 34, 34, 343, 43, 2]
let n = 10;
let new_L = heap_sort(L);
console.log(new_L.slice(new_L.length-n, new_L.length).reverse());

/**
 [ 3234, 343, 343, 234, 212, 45, 43, 43, 43, 34 ]
 */

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值