今天在接受采访时,我被告知编写一个程序,该程序将在未排序的数组中输出第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,这是第四高的数字。
但是面试官告诉了一个更好的解决方案。
你能告诉我还是给我一个提示,怎样才能找到更好的解决方案呢? 一些数据结构技术?
答案 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]);
}