关于10亿数字里面查询出最大的N位数的代码实现

问题:
在10亿个数字里面,找出最大的前N个数字。

代码:

/**
 * 获取TopN
 * @param {*} arr 原始数组
 * @param {*} topN 需要获取最大值的数量,正整数
 */
function getTopN(arr, topN) {

    //链表结构,用来存储topN的信息
    //链表结构更容易删除插入
    //链表内部元素的结构  {val:0,prev:null,next:null}
    var linkedList = {
        length: 0,//当length为1时候,只有first元素,没有last元素
        first: null,//头元素的prev为null
        last: null//尾元素的next为null
    };

    var len = arr.length;
    //循环需要进行Top获取的数组
    //首先对前topN的数组元素进行排序,以后的数组元素值进行比较,进行元素的插入与删除操作即可
    for (var i = 0; i < len; i++) {

        //链表是否已经满了
        var isDone = linkedList.length >= topN ? true : false;

        //如果链表满了
        //说明链表中的元素已经满了则需要对linkedList内部的元素进行比较,需要进行删除插入等操作了
        if (isDone) {
            //如果链表的最后一个元素的值都大于等于arr[i]
            //则说明arr[i]比链表中的任意一个都小于等于,则可以抛弃,进入下一次循环
            if (linkedList.last.val >= arr[i]) continue;
        }

        //如果arr[i]不小于最后的元素,则需要对链表进行循环,插入适合的位置上


        //如果length == 0说明没有元素,表示链表结构才刚开始,需要进行赋值操作
        if (linkedList.length == 0) {
            linkedList.first = {
                val: arr[i],
                prev: null,
                next: null
            }

            linkedList.length++;
            continue;
        }

        var item = linkedList.first;

        //有初始元素,则进行可以循环
        while (item) {
            //如果内部元素的值大于arr[i],则进入下一个循环
            if (item.val > arr[i]) {

                //如果链表已经满了,则进入下一个循环,因为在链表满了情况下,下一个必然会有值
                if (isDone) {
                    item = item.next;
                    continue;
                }

                //如果没有满,且链表的长度为1,表示现在只有头元素,没有尾元素
                if (linkedList.length == 1) {
                    linkedList.last = {
                        val: arr[i],
                        prev: item,
                        next: null
                    }
                    linkedList.first.next = linkedList.last;
                    linkedList.length++;
                    break;
                }

                //即没有满又不是length为1则继续循环
                item = item.next;
                continue;
            }
            //如果内部元素的值小于arr[i],则插入
            //将该内部元素的上级给arr[i]新建的元素,arr[i]新建的元素的下级为该内部元素
            var newTemp = {
                val: arr[i],
                prev: item.prev,
                next: item
            }

            //内部元素原本的上级的下级变成arr[i]的新建元素
            //当内部元素原本的上级不存在的时候,即该内部元素为头元素,则不需要进行如此操作
            if (item.prev) item.prev.next = newTemp;

            //将该内部元素的上级变成arr[i]新建的元素
            item.prev = newTemp;

            //如果arr[i]的新建元素的上级为null,则该新建元素为新的头元素,则将链表的first属性重新赋值
            if (!newTemp.prev) linkedList.first = newTemp;

            //如果链表满了,则需要进行最后元素的删除与重新赋值操作
            if (isDone) {
                //删除最后的元素,将最后元素的前一个元素赋值给新的最后元素
                //同时将新的最后元素的next赋值为null
                linkedList.last = linkedList.last.prev;
                linkedList.last.next = null;
            } else {
                if (linkedList.length == 1) {
                    linkedList.last = newTemp.next;
                }
                linkedList.length++;
            }
            break;
        }
    }


    var temp = [];
    var item = linkedList.first;
    while (item) {
        temp.push(item.val);
        item = item.next;
    }
    return temp;
}

逻辑:
先将前N个数字进行大小排序,然后后面的数组元素与前N个排好序的进行比较。

JS中没有链表这个数据结构,因此代码繁杂了一点,若是JAVA可以直接用LinkedList来做。

时间复杂度:
O(n)

一开始的排序用来插入排序的思想,N位之后则是链表的比较,删除与插入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值