所以,我正在努力应对这一挑战,以返回数组中的第三大数字。我已经解决了,直到我意识到我必须考虑到重复的数字。我通过添加3层for变量i
,j
和k
来处理这个问题。你会在代码中看到我的意思。这不是非常有效或可扩展。
我的问题是,如何优化此代码?我应该使用哪些其他方法?
function thirdGreatest (arr) {
arr.sort(function(a, b) {
if (a < b) {
return 1;
} else if (a > b) {
return -1;
} else {
return 0;
}
});
for ( var i = 0; i < arr.length; i++) {
for (var j = 1; j < arr.length; j++) {
for (var k = 2; k < arr.length; k++) {
if (arr[i] > arr[j]) {
if (arr[j] > arr[k]) {
return arr[k];
}
}
}
}
}
}
console.log(thirdGreatest([5, 3, 23, 7,3,2,5,10,24,2,31, 31, 31])); // 23
console.log(thirdGreatest([5, 3, 23, 7,3,2,5,10,24,2,31])) // 23
console.log(thirdGreatest([5, 3, 7, 4])); // 4
console.log(thirdGreatest([2, 3, 7, 4])); // 3
答案 0 :(得分:3)
由于你已经对数组进行了排序,看起来你应该很好地迭代列表并跟踪你已经看过的数字。当您看到三个不同的数字时,请返回当前的数字:
var seen = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== seen[0]) {
if (seen.length === 2) {
return arr[i];
}
seen.unshift(arr[i]);
}
}
function thirdGreatest (arr) {
arr.sort(function(a, b) {
return b - a;
});
var seen = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== seen[0]) {
if (seen.length === 2) {
return arr[i];
}
seen.unshift(arr[i]);
}
}
}
console.log(thirdGreatest([5, 3, 23, 7,3,2,5,10,24,2,31, 31, 31])); // 23
console.log(thirdGreatest([5, 3, 23, 7,3,2,5,10,24,2,31])) // 23
console.log(thirdGreatest([5, 3, 7, 4])); // 4
console.log(thirdGreatest([2, 3, 7, 4])); // 3
注意:您可以将排序回调简化为
arr.sort(function(a, b) {
return b - a;
});
// With arrow functions:
// arr.sort((a, b) => b - a);
回调必须返回一个更大,更小或等于0
的数字,它不必完全是-1
或1
。
答案 1 :(得分:3)
一个 - &#34;行&#34; r使用Set
删除重复项
Array.from(new Set(arr)).sort(function(a, b) {
return b - a;
})[2];
答案 2 :(得分:3)
最佳解决方案是在单次通过O(n)时间内完成此操作。您不需要对数组进行排序 - 这样做可以使您的解决方案至少(n log n)。
要在单次传递中执行此操作,您只需要三个临时变量:maximum,secondLargest,thirdLargest。只需遍历数组并根据需要更新这些值(即当你替换最大值时它会变成第二大等等......)。最后,当您看到重复项(即currentValue == secondLargest)时,只需忽略它们。他们不会影响结果。
不要忘记检查边缘情况。您无法为[2,2,2,2,2]或[3,2]提供答案。
答案 3 :(得分:1)
尝试考虑一下您可以在这里使用的数据结构。我建议一套。每次添加嵌套循环时,您的函数都会以指数方式变慢。
<强>编辑:强>
function thirdGreatest(arr) {
var s = Array.from(new Set(arr)).sort(function(a, b) {
return a - b;
})
return s[2] || s[1] || s[0] || null;
}
我们需要能够处理:
[1,2,1,2] // 2
[1,1,1,1] // 1
[] // null
这假设你传入一个数组。
null
如果您想要第三大或无,请返回s[2] || null
答案 4 :(得分:0)
许多其他答案需要多次循环初始数组。以下分类和重复删除同时进行。它不那么简洁,但性能更高。
const inputArray = [5,3,23,24,5,7,3,2,5,10,24,2,31,31,31];
const getThirdGreatest = inputArray => {
const sorted = [inputArray[0]]; // Add the first value from the input to sorted, for our for loop can be normalized.
let migrated = false;
let j;
for(let i = 1; i<inputArray.length; i++) { // Start at 1 to skip the first value in the input array
for(j=0; j<sorted.length; j++) {
if(sorted[j] < inputArray[i]) {
// If the input value is greater than that in the sorted array, add that value to the start of the sorted array
sorted.splice(j,0,inputArray[i]);
migrated = true;
break;
} else if(sorted[j] === inputArray[i]) {
// If the input value is a duplicate, ignore it
migrated = true;
break;
}
}
if(migrated === false) {
// If the input value wasn't addressed in the loop, add it to the end of the sorted array.
sorted[sorted.length] = inputArray[i];
} else {
migrated = false;
}
}
// Return the third greatest
return sorted[2];;
};
const start = performance.now();
getThirdGreatest(inputArray); // 23
const end = performance.now();
console.log('speed: ', end - start); // 0.1 - 0.2ms
答案 5 :(得分:0)
一次迭代O(n)和非常快速的方法就是让你自己的Set像对象一样。有利的一点是,在构建“独特”元素的“排序”列表时,根本不进行比较,从而带来巨大的效率。当处理长度超过1,000,000的巨大列表时,差异非常明显。
var arr = [5, 3, 23, 7,3,2,5,10,24,2,31, 31, 31],
sorted = Object.keys(arr.reduce((p,c)=> (p[c] = c, p),Object.create(null))),
third = sorted[sorted.length-3];
document.write(third);
如果您认为Object.keys可能不会返回已排序的数组(我还没有看到它),那么您可以像在Set方法中那样对它进行排序。
在这里,我尝试了1,000,000个项目数组,并在45msecs左右返回正确的结果。 10,000,000个项目阵列需要约450毫秒,比本问题下列出的其他O(n)解决方案少50%。
var arr = [],
sorted = [],
t0 = 0,
t1 = 0,
third = 0;
for (var i = 0; i<1000000; i++) arr[i] = Math.floor(Math.random()*100);
t0 = performance.now();
sorted = Object.keys(arr.reduce((p,c)=> (p[c] = c, p),Object.create(null)));
third = sorted[sorted.length-3];
t1 = performance.now();
document.write(arr.length + " size array done in: " + (t1-t0) + "msecs and the third biggest item is " + third);