Issolvi problema minn intervista Google f'JavaScript: 4 modi differenti

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".

Skillbox jirrakkomanda: Kors prattiku "Mobile Developer PRO".

Dikjarazzjoni tal-problema

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.

Soluzzjoni 1: Forza bruta

Il-kumplessità tal-ħin: O(N²).
Komplessità spazjali: O(1).

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²).


Soluzzjoni 2: Tiftix Binarju

Il-kumplessità tal-ħin: O(Nlog(N)).
Komplessità spazjali: O(1)
.

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.


Soluzzjoni 3: Ħin lineari

Il-kumplessità tal-ħin: O(N).
Komplessità spazjali: O(1).

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?

Soluzzjoni 4

Il-kumplessità tal-ħin: O(N).
Komplessità spazjali: O(N).

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).

Skillbox jirrakkomanda:

Sors: www.habr.com

Żid kumment