找到未排序数组中的第N个最高数字

时间:2015-04-11 14:57:04

标签: javascript arrays sorting

今天在接受采访时,我被告知编写一个程序,该程序将在未排序的数组中输出第n个最高的数字,

我用javascript解决了这个问题,程序如下,

var fn50 = function(){
    var reverseSort = function(myArray,highest){
        var x = 0,
            y = 0,
            z = 0,
            temp = 0,
            totalNum = myArray.length, // total numbers in array
            flag = false, // is the numbers sorted in reverse while iteration
            isAchieved = false; // whether we achieved the nth highest

        while(x < totalNum){
            y = x + 1; // start comparing 'yth' number which is next to 'xth' number.

            if(y < totalNum){
                // start comparing 'xth' with the next number, and if 'xth' number less than its next position number, just swipe them
                for(z = y; z < totalNum; z++){

                    if(myArray[x] < myArray[z]){
                        temp = myArray[z];
                        myArray[z] = myArray[x];
                        myArray[x] = temp;
                        flag = true; // if number swiping done ?
                    }else{
                        continue;
                    }   
                }                   
            }

            if(flag){
                flag = false;
            }else{
                x++; // x holds the max number in series, now move to next position to find next highest number 
                if(x > highest){ // if x is what the desired max number which we want flag it and break the loop to escape further iteration.
                    isAchieved = true;
                }   
            }
            if(isAchieved){
                break;
            }
        }

        print(myArray[(highest - 1)]);  
    };

    reverseSort([12,56,78,34,11,100,95],4); // passing the unsorted array of number's, and finding the 4th highest number
};

fn50();

我得到了所需的输出,即上面的数组中答案是56,这是第四高的数字。

但是面试官告诉了一个更好的解决方案。

你能告诉我还是给我一个提示,怎样才能找到更好的解决方案呢? 一些数据结构技术?

6 个答案:

答案 0 :(得分:4)

排序并选择k个最高数字需要O(n log(n))时间,其中n是元素数量。在参考书目中,有medians of medians algorithm,它允许我们在线性时间内选择k最高或最小,无论k具有什么值。如果你问到所需的元素是否是数组的中位数,你可以找出面试官是否考虑过这种算法。中位数是位置n / 2的元素,这被认为是最难的情况。

但是对于一次采访,这是一个复杂的算法。如果k通常较小,则可以根据heap的结构应用以下算法。您可以在线性时间内将数组转换为堆。然后提取k次最大元素。这将花费O(n + k * log(n))时间,小k = ο(n / log(n)是线性的。

k与常数一样小,如4,具有更简单的线性算法。每次我们扫描数组并删除最大的数组。这需要O(k * n)时间,因为k是常量,O(k * n) = O(n)

答案 1 :(得分:1)

我想出了自己的解决方案:

const nthlargest = (arr, n) => {
    let newArr = [arr[0]];
    for (let index = 1; index < arr.length; index++) {
        const element = arr[index];
        // push to end
        if (element > newArr[index - 1]) {
            newArr.push(element);
        } else {
            let insertPos = 0;
            // if greater than first and less than last
            if (newArr[0] < element && element < newArr[index - 1]) {
                for (let j = 0; j < newArr.length; j++) {
                    if (newArr[j] > element) {
                        insertPos = j;
                    }
                }
            }
            //insert at specified pos
            newArr.splice(insertPos, 0, element);
        }
    }
    return newArr[n];
}

console.log(nthlargest([43, 56, 23, 89, 88, 90, 99, 652], 4));
// counting from 0
// 89

这无需对原始数组进行排序,否则会容易得多。

答案 2 :(得分:1)

<script>
    function nthlargest(array, highest) {
        array.sort();
        l=array.length;
        if(highest>l)
            return("undefined");
        else
            return(array[l-highest+1]);
    }
    document.write(nthlargest([23, 652, 43, 89, 23, 90, 99, 88], 2));
</script>

答案 3 :(得分:0)

排序是我能想到的最简单的方法。

但是看起来你创建了自己的排序实现。

为什么不使用Array.sort功能?

function nthHighest(numbers, n) {
    var sorted = numbers.sort(function (a, b) {
        return a - b;
    });
    return sorted[sorted.length - n];
}

你可以通过反向排序来简化算术,这只是b - a而不是a - b,然后你不需要从后面拉,这只是一种美化改进。 / p>

function nthHighest(numbers, n) {
    var sorted = numbers.sort(function (a, b) {
        return b - a;
    });
    return sorted[n - 1];
}

您还可以迭代数组一次,按排序顺序将每个元素复制到一个新数组中,然后再使用下划线将Nth转换为最后一个元素,以实现二进制搜索。

function nthHighest(numbers, n) {
    var sorted = [];
    numbers.forEach(function (number) {
        sorted.splice(_.sortedIndex(sorted, number), 0, number);
    });
    return sorted[numbers.length - n];
}

但这基本上是对同一概念的一种旋转:排序并采用N.由于重组,这种方法在链表上的表现也比纯数组好,但这可以是一个单独的练习。

答案 4 :(得分:0)

我尝试使用quickselect as JuniorCompressor suggested来实现这一点。 但我想知道这是否真的是最快的方式。我想枢轴的计算可以更有效率。

var nthLargest = function(list, n) {
  var i, a = 0, b = list.length, m, pivot;
  if(n < 1) throw new Error("n too small");
  if(list.length < n) throw new Error("n too large");
  list = list.slice(0);
  var swap = function(list, a, b) {
    var temp = list[a];
    list[a] = list[b];
    list[b] = temp;
  }
  //returns the index of the first element in the right sublist
  var partition = function(list, pivot, a, b) {
    b--;
    while(a <= b) {
      if(list[a] <= pivot) a++;
      else if(list[b] > pivot) b--;
      else swap(list, a, b);
    }
    return a;
  }
  while(b - a > 1) {
    for(i = a, pivot = 0; i < b; i++) {
      pivot += list[i];
    }
    pivot /= b-a;
    m = partition(list, pivot, a, b);
    if(b - m >= n) a = m; // select right sublist
    else { // select left sublist
      if(m === b) return list[a]; // all elements in sublist are identical
      n -= b - m;
      b = m;
    }
  }
  if(n !== 1) throw new Error();
  return list[a];
}

答案 5 :(得分:0)

使用排序数组方法

function nthLargest(array, n){

    array.sort(function(a, b) {
        return b - a; //organises the array in descending organises
      });

    let i = n - 1; //i is the index of the nth largest number
    
    console.log(array[i]);

}