Issolvi problema minn intervista Google f'JavaScript: 4 modi differenti
Meta kont qed nistudja l-prestazzjoni tal-algoritmi, iltqajt ma' dan Dan huwa video ta' intervista finta ta' Google.. Mhux biss tagħti idea ta 'kif isiru l-intervisti f'korporazzjonijiet kbar tat-teknoloġija, iżda tippermetti wkoll li tifhem kif il-problemi algoritmiċi jiġu solvuti bl-aktar mod effiċjenti possibbli.
Dan l-artikolu huwa tip ta 'akkumpanjament għall-video. Fiha nipprovdi kummenti dwar is-soluzzjonijiet kollha murija, flimkien mal-verżjoni tiegħi stess tas-soluzzjoni f'JavaScript. L-sfumaturi ta 'kull algoritmu huma diskussi wkoll.
Infakkrukom:għall-qarrejja kollha ta '"Habr" - skont ta' 10 rublu meta tirreġistra fi kwalunkwe kors ta 'Skillbox billi tuża l-kodiċi promozzjonali "Habr".
Aħna jingħataw firxa ordnata u valur speċifiku. Imbagħad jintalab li toħloq funzjoni li tirritorna vera jew falza skont jekk is-somma ta 'kwalunkwe żewġ numri fil-firxa tistax tkun ugwali għal valur partikolari.
Fi kliem ieħor, hemm żewġ numri interi fil-firxa, x u y, li meta miżjuda flimkien huma ugwali għall-valur speċifikat?
Eżempju A
Jekk ningħataw firxa [1, 2, 4, 9] u l-valur huwa 8, il-funzjoni se terġa 'lura falza għaliex l-ebda żewġ numri fl-array ma jistgħu jammontaw għal 8.
Eżempju B
Imma jekk hija firxa [1, 2, 4, 4] u l-valur huwa 8, il-funzjoni għandha tirritorna vera għaliex 4 + 4 = 8.
L-aktar tifsira ovvja hija li tuża par ta 'linji nested.
const findSum = (arr, val) => {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
if (i !== j && arr[i] + arr[j] === val) {
return true;
};
};
};
return false;
};
Din is-soluzzjoni mhix effiċjenti għaliex tiċċekkja kull somma possibbli ta 'żewġ elementi fl-array u tqabbel ukoll kull par ta' indiċi darbtejn. (Per eżempju, meta i = 1 u j = 2 huwa fil-fatt l-istess bħal meta tqabbel ma 'i = 2 u j = 1, iżda f'din is-soluzzjoni nippruvaw iż-żewġ għażliet).
Minħabba li s-soluzzjoni tagħna tuża par ta' linji nested for loops, hija kwadratika b'kumplessità ta' ħin O(N²).
Peress li l-arrays huma ordnati, nistgħu nfittxu soluzzjoni billi tuża tfittxija binarja. Dan huwa l-aktar algoritmu effiċjenti għall-arrays ordnati. It-tfittxija binarja nnifisha għandha ħin ta' tħaddim ta' O(log(N)). Madankollu, xorta trid tuża for loop biex tiċċekkja kull element mal-valuri l-oħra kollha.
Hawn kif tista' tidher soluzzjoni. Biex nagħmlu l-affarijiet ċari, nużaw funzjoni separata biex tikkontrolla t-tfittxija binarja. U wkoll il-funzjoni removeIndex(), li tirritorna l-verżjoni tal-firxa nieqes l-indiċi mogħti.
const findSum = (arr, val) => {
for (let i = 0; i < arr.length; i++){
if (binarySearch(removeIndex(arr, i), val - arr[i])) {
return true;
}
};
return false;
};
const removeIndex = (arr, i) => {
return arr.slice(0, i).concat(arr.slice(i + 1, arr.length));
};
const binarySearch = (arr, val) => {
let start = 0;
let end = arr.length - 1;
let pivot = Math.floor(arr.length / 2);
while (start < end) {
if (val < arr[pivot]) {
end = pivot - 1;
} else if (val > arr[pivot]) {
start = pivot + 1;
};
pivot = Math.floor((start + end) / 2);
if (arr[pivot] === val) {
return true;
}
};
return false;
};
L-algoritmu jibda mill-indiċi [0]. Imbagħad toħloq verżjoni tal-firxa eskluża l-ewwel indiċi u tuża tfittxija binarja biex tara jekk xi wieħed mill-valuri li jifdal jistax jiġi miżjud mal-firxa biex tipproduċi s-somma mixtieqa. Din l-azzjoni titwettaq darba għal kull element fl-array.
Il-linja for innifsu se jkollu kumplessità ta 'ħin lineari ta' O (N), iżda ġewwa l-linja for aħna nwettqu tfittxija binarja, li tagħti kumplessità ta 'ħin ġenerali ta' O (Nlog (N)). Din is-soluzzjoni hija aħjar minn dik preċedenti, iżda għad hemm lok għal titjib.
Issa se nsolvu l-problema, filwaqt li niftakru li l-firxa hija magħżula. Is-soluzzjoni hija li tieħu żewġ numri: wieħed fil-bidu u wieħed fl-aħħar. Jekk ir-riżultat ikun differenti minn dak meħtieġ, imbagħad ibdel il-punti tal-bidu u tat-tmiem.
Eventwalment aħna jew niltaqgħu mal-valur mixtieq u nirritornaw veru, jew il-punti tal-bidu u tat-tmiem se jikkonverġu u jirritorna foloz.
const findSum = (arr, val) => {
let start = 0;
let end = arr.length - 1;
while (start < end) {
let sum = arr[start] + arr[end];
if (sum > val) {
end -= 1;
} else if (sum < val) {
start += 1;
} else {
return true;
};
};
return false;
};
Issa kollox huwa tajjeb, is-soluzzjoni tidher li hija l-aħjar. Imma min jista 'jiggarantixxi li l-firxa kienet ordnata?
Xi allura?
L-ewwel daqqa t'għajn, stajna sempliċement ordnaw il-firxa l-ewwel u mbagħad użajna s-soluzzjoni ta 'hawn fuq. Imma dan kif se jaffettwa l-ħin tal-eżekuzzjoni?
L-aħjar algoritmu huwa quicksort bil-kumplessità tal-ħin O (Nlog (N)). Jekk nużawha fis-soluzzjoni ottima tagħna, se tbiddel il-prestazzjoni tagħha minn O (N) għal O (Nlog (N)). Huwa possibbli li ssib soluzzjoni lineari b'firxa mhux ordnata?
Iva, hemm soluzzjoni lineari; biex nagħmlu dan, irridu noħolqu firxa ġdida li fiha l-lista ta 'logħbiet li qed infittxu. Il-kompromess hawnhekk huwa aktar użu tal-memorja: hija l-unika soluzzjoni fil-karta b'kumplessità spazjali akbar minn O (1).
Jekk l-ewwel valur ta 'firxa partikolari huwa 1 u l-valur tat-tfittxija huwa 8, nistgħu nżidu l-valur 7 mal-firxa ta' "valuri ta 'tfittxija".
Imbagħad, hekk kif nipproċessaw kull element tal-firxa, nistgħu niċċekkjaw il-firxa ta '"valuri ta' tfittxija" u naraw jekk wieħed minnhom hux ugwali għall-valur tagħna. Jekk iva, irritorna vera.
const findSum = (arr, val) => {
let searchValues = [val - arr[0]];
for (let i = 1; i < arr.length; i++) {
let searchVal = val - arr[i];
if (searchValues.includes(arr[i])) {
return true;
} else {
searchValues.push(searchVal);
}
};
return false;
};
Il-bażi tas-soluzzjoni hija for loop, li, kif rajna hawn fuq, għandha kumplessità ta 'ħin lineari ta' O (N).
It-tieni parti iterattiva tal-funzjoni tagħna hija Array.prototype.include(), metodu JavaScript li jirritorna veru jew falz skont jekk l-array fihx il-valur mogħti.
Biex insemmu l-kumplessità tal-ħin ta 'Array.prototype.includes(), nistgħu nħarsu lejn il-polyfill ipprovdut minn MDN (u miktub f'JavaScript) jew nużaw metodu fil-kodiċi sors ta' magna JavaScript bħal Google V8 (C++).
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(valueToFind, fromIndex) {
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(valueToFind, elementK) is true, return true.
if (sameValueZero(o[k], valueToFind)) {
return true;
}
// c. Increase k by 1.
k++;
}
// 8. Return false
return false;
}
});
}
Hawnhekk il-parti iterattiva ta' Array.prototype.include() hija l-loop while fil-pass 7 li (kważi) jaqsam it-tul kollu tal-firxa mogħtija. Dan ifisser li l-kumplessità tal-ħin tagħha hija wkoll lineari. Ukoll, peress li huwa dejjem pass wara l-firxa ewlenija tagħna, il-kumplessità tal-ħin hija O (N + (N - 1)). Billi tuża Big O Notation, nissimplifikawha għal O(N) - għaliex huwa N li għandu l-akbar impatt meta jżid id-daqs tal-input.
Rigward il-kumplessità spazjali, hija meħtieġa firxa addizzjonali li t-tul tagħha tirrifletti l-firxa oriġinali (nieqes waħda, iva, iżda li tista 'tiġi injorata), li tirriżulta f'kumplessità spazjali O(N). Ukoll, żieda fl-użu tal-memorja tiżgura effiċjenza massima tal-algoritmu.
Nispera li ssib l-artiklu utli bħala suppliment għall-intervista bil-vidjo tiegħek. Juri li problema sempliċi tista’ tissolva b’diversi modi differenti b’ammonti differenti ta’ riżorsi użati (ħin, memorja).