我正在嘗試為一個非常常見的演算法撰寫解決方案。輸入是未排序的陣列,輸出應該是排序后的三個最高值的陣列。
我的方法是默認將陣列的前三個專案設定為最大的三個。從 idx 3 開始遍歷陣列中的每個元素,并通過一系列函式運行每個值,該函式將該值與當前 3 個最高值進行比較。
我的代碼
function findThreeLargestNumbers(array) {
let currentHighest = array[0];
let secondHighest = array[1];
let thirdHighest = array[2]
for(i = 3; i < array.length; i ){
compareFirst(array[i], currentHighest, secondHighest, thirdHighest);
}
console.log(currentHighest, secondHighest, thirdHighest)
}
function compareFirst(value, currentHighest, secondHighest, thirdHighest){
if(value >= currentHighest){
let pastFirst = currentHighest;
currentHighest = value;
compareSecond(pastFirst, secondHighest, thirdHighest)
}else{
compareSecond(value, secondHighest, thirdHighest)
}
}
function compareSecond(value, secondHighest, thirdHighest){
if(value >= secondHighest){
let pastSecond = secondHighest;
secondHighest = value;
compareThird(pastSecond, thirdHighest);
}else{
compareThird(value, thirdHighest)
}
}
function compareThird(value, thirdHighest){
if(value >= thirdHighest){
thirdHighest = value;
}
}
在這一切都完成之后,console.log我發現我上面設定的變數沒有任何變化。這意味著函式不會更新父函式中設定的值。
我的方法可能有路要走,但我對為什么這些值不會在全球范圍內更新感到困惑。
uj5u.com熱心網友回復:
JavaScript 具有通過值傳遞的資料型別 -原始型別(數字、布林值、字串等)和通過參考傳遞的資料型別 -物件(陣列、函式、物件)。
當您將原始型別作為函式的引數傳遞時,您只是在傳遞變數的值。因此,當您更改作為原始型別傳遞的函式的引數時,此更改不會影響傳遞到函式外部的變數。
當您將參考資料型別作為函式的引數傳遞時,您將此變數的地址傳遞給函式,而不是值本身。這就是為什么如果你改變通過參考傳遞的引數,那么它也會在函式之外被改變。
在您的情況下,由于您將數字作為 compareFirst、compareSecond 和 compareThird 函式的引數傳遞,因此它們的值不會改變。
uj5u.com熱心網友回復:
正如其他人所說,問題是將原始型別作為函式引數傳遞,導致它們的值僅在本地函式范圍內更改,而不在全域范圍內更改。使用Reference Data Type,在這種情況下:存盤值的highestValues 物件允許我根據需要從子函式中全域更新它們。
解決方案
function findThreeLargestNumbers(array) {
let highestValues = {}
for(i = 0; i < array.length; i ){
compareFirst(array[i], highestValues);
}
return [highestValues['3'], highestValues['2'], highestValues['1']];
}
function compareFirst(value, highestValues){
if(!highestValues['1']){
highestValues['1'] = value;
}else if(value >= highestValues['1']){
let pastFirst = highestValues['1'];
highestValues['1'] = value;
compareSecond(pastFirst, highestValues)
}else{
compareSecond(value, highestValues)
}
}
function compareSecond(value, highestValues){
if(!highestValues['2']){
highestValues['2'] = value;
}else if(value >= highestValues['2']){
let pastSecond = highestValues['2'];
highestValues['2'] = value;
compareThird(pastSecond, highestValues);
}else{
compareThird(value, highestValues)
}
}
function compareThird(value, highestValues){
if(!highestValues['3']){
highestValues['3'] = value;
}else if(value >= highestValues['3']){
highestValues['3'] = value;
}
}
uj5u.com熱心網友回復:
其他人已經解釋了您的代碼有什么問題。
如果您正在尋找一種更簡單的方法,我們可以一次將數字折疊到我們的目標陣列中,使用Array.prototype.reduce,從三個副本的陣列開始-Infinity。
在每個步驟中,我們測驗新數字是否大于最大數字、大于第二大數字、大于第三大數字,或者以上都不是,并回傳一個插入了新數字的三元素陣列在正確的地方。它可能看起來像這樣:
const topThree = (ns) => ns.reduce ((m, n) =>
n > m[2] ? [m[1], m[2], n] : n > m[1] ? [m[1], n, m[2]] : n > m[0] ? [n, m[1], m[2]] : m,
[-Infinity, -Infinity, -Infinity]
)
console.log(topThree([8, 6, 7, 5, 3, 0, 9]))
uj5u.com熱心網友回復:
如果您想撰寫更少的代碼,您可以考慮類似的插入排序:
function findKLargestNumbers(arr, k = 3) {
// get first three element and sort them
let ret = arr.slice(0, k)
ret.sort()
// iterate other elements
for (i = k; i < arr.length; i) {
let x = arr[i];
for (j = 0; j < k; j) {
// if current value greater then swap (imporant: without break)
if (x > ret[j]) {
[x, ret[j]] = [ret[j], x]
}
}
}
return ret
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/487772.html
標籤:javascript 数组 算法 排序
