n个数字的一维数组如何从中选择指定数量的最大值

243 阅读5分钟

有这样一个场景,n个数字组成的一维数组,如下:

let arr = [11,23,332,24,134,3134,83,665,22,74];

如果要从中选取多个(如3个)最大的数字,如何处理呢?

解题思路

二进制的数据是由0和1来构成的,将每个数字都转换成2进制32位的数字,再切割转换为数组,然后循环数组arr,其中每一项出现数字1的下标较小的,即认为该项数字最大,将该项收集起来,达到选取数量了就停止,再将收集到的数字转为10进制,完成选择。

1.先将arr数组循环,再将数组的每一项由10进制转为2进制32位数,分割后保存。

for(var i=0;i<arr.length;i++){
    let resArry = [];
    resArry = arr[i].toString(2).split('');
    for (let r = resArry.length; r < 32; r++) {
        resArry.unshift(0);
    }
    arr[i] = resArry;
}

数组的每一项如下图:

2.处理完arr数组内的数字之后,循环数组arr,对每一项都从下标0开始,判断是否为1。如是,收集到代表最大值的数组中,如果不是,收集到另外的数组中。

//定义递归函数处理收集最大值
function digitalsort(e) {
    let newarr = [];//用来保存最大值
    let oldarr = [];//用来保存未被选为最大值的数字
    for (let i = 0; i < arguments[0].length; i++) {
        if (arguments[0][i][arguments[1]] == 1) {
            newarr.push(arguments[0][i]);
        } else {
            oldarr.push(arguments[0][i]);
        }
    }
}
digitalsort(arr,0);

3.通常不会马上有项进入newarr(也就是最大值的集合),因此会遇到arguments[0]的长度和oldarr的长度相等,这时就要将下标游标加1,对比arguments[0]每一项的下一下标,直到下标+1为31,也就是每一项的最大长度。

if ((oldarr.length == arguments[0].length) && arguments[1] <= 30) {
    digitalsort(arguments[0], arguments[1] + 1);
}

4.如果某项的下标为1,该项将被最大值集合newarr收集,而我们需要的最大值是3个,newarr数组长度小于3,就要进行递归。

//oldarr为arr中非最大值的集合,下标增加1,同时传入最大值的集合newarr,newarr长度为3之后,
//数组中的项将被处理为10进制并返回
digitalsort(oldarr, arguments[1] + 1, newarr);

5.对于上一步传入的newarr在函数中要做处理,如又找到了新的最大值,需要跟传入的newarr,也就是arguments[2]合并;如果在本次递归中没有找到新的最大值,依旧返回arguments[2]。

let arrlength = 0;//标记传入最大值集合的长度
if (arguments[2] && arguments[2].length > 0) {
    arrlength = arguments[2].length;
}
...
//本轮递归收集到的最大值与传入的最大值集合的数量之和小于3
if(newarr.length>0&&(newarr.length < 3 - arrlength)){
    if (arguments[1] <= 30) {
        if (arrlength > 0) {
            for (let i = 0; i < arguments[2].length; i++) {
                //将两组合并
                newarr.unshift(arguments[2][i]);
            }
        }
        digitalsort(oldarr, arguments[1] + 1, newarr);
    }
}
//如本轮递归未收集到最大值,就依旧传递最大值集合进入下一轮递归
if ((oldarr.length == arguments[0].length) && arguments[1] <= 30) {
    if (arrlength > 0) {
        digitalsort(arguments[0], arguments[1] + 1, arguments[2]);
    }else{
        digitalsort(arguments[0], arguments[1] + 1);
    }
}

6.还有一种情况,在本轮递归中,arr数组每一项的当前下标所对应的值(arguments[0][i][arguments[1]])为1的情况,超过了3个,这时就需要比对arguments[1]+1的情况了。此时只需要传入符合本轮最大值筛选的项的集合就可以了。

if (newarr.length > 3 - arrlength) {
    if (arguments[1] <= 30) {
        if (arrlength > 0) {
            digitalsort(newarr, arguments[1] + 1, arguments[2]);
        } else {
            digitalsort(newarr, arguments[1] + 1);
        }
    }
}

7.如果本轮收集的最大值和传入的最大值集合的总和等于3了,将两组集合合并,遍历数组转换为10进制数后,返回结果。

if (newarr.length == 3 - arrlength) {
    if (arrlength > 0) {
        for (var i = 0; i < arguments[2].length; i++) {
            newarr.unshift(arguments[2][i]);
        }
    }
    for (var k = 0; k < newarr.length; k++) {
        newarr[k] = parseInt(newarr[k].join(''),2);
    }
    return newarr;
}

8.结束之后还要来总结一下,其实主要是把数组每个项都转换成2进制的32位数字,然后从高位进行比较,因为2进制只有0和1两个数字,不像十进制有10个数字,有两个数字的好处就是只需要判断是否为1,就能确定当前值是否为最大值,然后收集或者放入待判断的数组oldarr中,最终集齐规定的数量,再将数字转为10进制,返回结果完成。 附上完整代码:

var arr = [11,23,332,24,134,3134,83,665,22,74];
for(var i=0;i<10;i++){
    var resArry = [];
	resArry = arr[i].toString(2).split('');
    for (var r = resArry.length; r < 32; r++) {
        resArry.unshift(0);
    }
        arr[i] = resArry;
}
digitalsort(arr,0);
function digitalsort(e) {
    var newarr = [];
    var oldarr = [];
    var arrlength = 0;
    if (arguments[2] && arguments[2].length > 0) {
        arrlength = arguments[2].length;
    }
    for (var i = 0; i < arguments[0].length; i++) {
        if (arguments[0][i][arguments[1]] == 1) {
            newarr.push(arguments[0][i]);
        } else {
            oldarr.push(arguments[0][i]);
        }
    }
    if (newarr.length > 3 - arrlength) {
        if (arguments[1] <= 30) {
            if (arrlength > 0) {
                digitalsort(newarr, arguments[1] + 1, arguments[2]);
            } else {
                digitalsort(newarr, arguments[1] + 1);
            }
        }
    } else if (newarr.length == 3 - arrlength) {
        if (arrlength > 0) {
            for (var i = 0; i < arguments[2].length; i++) {
                newarr.unshift(arguments[2][i]);
            }
        }
        for (var k = 0; k < newarr.length; k++) {
            newarr[k] = parseInt(newarr[k].join(''),2);
        }
        console.log(newarr);
        return newarr;
    } else if(newarr.length>0&&(newarr.length < 3 - arrlength)){
        if (arguments[1] <= 30) {
            if (arrlength > 0) {
                for (var i = 0; i < arguments[2].length; i++) {
                    newarr.unshift(arguments[2][i]);
                }
            }
            digitalsort(oldarr, arguments[1] + 1, newarr);
        }
    }
    if ((oldarr.length == arguments[0].length) && arguments[1] <= 30) {
        if (arrlength > 0) {
            digitalsort(arguments[0], arguments[1] + 1, arguments[2]);
        }else{
            digitalsort(arguments[0], arguments[1] + 1);
        }
    }
}