Fadhb a réiteach ó agallamh le Google i JavaScript: 4 bhealach éagsúla

Fadhb a réiteach ó agallamh le Google i JavaScript: 4 bhealach éagsúla

Nuair a bhí mé ag déanamh staidéir ar fheidhmíocht na n-algartam, tháinig mé trasna air seo Seo físeán d'agallamh bréige le Google.. Ní hamháin go dtugann sé smaoineamh ar conas a dhéantar agallaimh ag corparáidí móra teicneolaíochta, ach ligeann sé duit tuiscint a fháil ar conas a réitítear fadhbanna algartamacha chomh héifeachtach agus is féidir.

Is cineál tionlacain é an t-alt seo leis an bhfíseán. Inti tugaim tuairimí ar na réitigh go léir a thaispeántar, chomh maith le mo leagan féin den réiteach i JavaScript. Pléitear freisin nuances gach algartam.

Meabhraímid: do léitheoirí uile "Habr" - lascaine de 10 rúbal nuair a chláraíonn siad in aon chúrsa Scilbox ag baint úsáide as an gcód bolscaireachta "Habr".

Molann Skillbox: Cúrsa praiticiúil "Forbróir Soghluaiste OCP".

An fhadhb a fhoirmiú

Tugtar eagar ordaithe agus luach sonrach dúinn. Iarrtar ansin feidhm a chruthú a fhilleann fíor nó bréagach ag brath ar cé acu an bhfuil suim dhá uimhir ar bith san eagar cothrom le luach tugtha.

I bhfocail eile, an bhfuil dhá shlánuimhir san eagar, x agus y, atá cothrom leis an luach sonraithe nuair a chuirtear le chéile iad?

Sampla A

Má thugtar eagar [1, 2, 4, 9] dúinn agus gurb é 8 an luach, fillfidh an fheidhm bréagach mar ní féidir le dhá uimhir san eagar suimiú suas le 8 a dhéanamh.

Sampla B

Ach más eagar é [1, 2, 4, 4] agus gurb é 8 an luach, ba cheart go mbeadh an fheidhm ar ais fíor mar gheall ar 4 + 4 = 8.

Réiteach 1: Fórsa brute

Castacht ama: O(N²).
Castacht spáis: O(1).

Is é an bhrí is soiléire ná péire lúb neadaithe a úsáid.

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;
};

Níl an réiteach seo éifeachtach mar seiceálann sé gach suim féideartha de dhá eilimint san eagar agus déanann sé comparáid idir gach péire innéacs faoi dhó. (Mar shampla, nuair a bhíonn i = 1 agus j = 2 i ndáiríre mar an gcéanna le comparáid a dhéanamh le i = 2 agus j = 1, ach sa réiteach seo déanaimid iarracht an dá rogha).

Toisc go n-úsáideann ár réiteach péire neadaithe le haghaidh lúb, tá sé cearnach le castacht ama O(N²).


Réiteach 2: Cuardach Dénártha

Castacht ama: O(Nlog(N)).
Castacht spáis: O(1)
.

Ós rud é go bhfuil na eagair ordaithe, is féidir linn cuardach a dhéanamh ar réiteach ag baint úsáide as cuardach dénártha. Is é seo an algartam is éifeachtaí le haghaidh eagair ordaithe. Tá am reatha O(log(N)) ag cuardach dénártha féin. Mar sin féin, ní mór duit fós le haghaidh lúb a úsáid chun gach eilimint a sheiceáil i gcoinne gach luachanna eile.

Seo an chuma a bheadh ​​ar réiteach. Chun rudaí a dhéanamh soiléir, bainimid úsáid as feidhm ar leith chun cuardach dénártha a rialú. Agus freisin an fheidhm removeIndex(), a thugann ar ais an leagan den eagar lúide an t-innéacs tugtha.

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;
};

Tosaíonn an algartam ó innéacs [0]. Cruthaíonn sé leagan den eagar ansin gan an chéad innéacs a áireamh agus úsáideann sé cuardach dénártha féachaint an féidir aon cheann de na luachanna atá fágtha a chur leis an eagar chun an tsuim atá ag teastáil a tháirgeadh. Déantar an gníomh seo uair amháin in aghaidh gach eilimint san eagar.

Beidh castacht ama líneach O(N) ag an lúb féin, ach taobh istigh den lúb le haghaidh déanaimid cuardach dénártha, a thugann castacht ama foriomlán O(Nlog(N)). Tá an réiteach seo níos fearr ná an ceann roimhe seo, ach tá spás ann fós le feabhsú.


Réiteach 3: Am líneach

Castacht ama: O(N).
Castacht spáis: O(1).

Anois déanfaimid an fhadhb a réiteach, ag cuimhneamh go bhfuil an t-eagar curtha in eagar. Is é an réiteach ná dhá uimhir a ghlacadh: ceann ag an tús agus ceann ag an deireadh. Má tá an toradh difriúil ón gceann riachtanach, ansin athraigh na pointí tosaigh agus deiridh.

Faoi dheireadh beidh muid ag teacht ar an luach inmhianaithe agus ar ais fíor, nó beidh na pointí tosaigh agus deiridh le chéile agus ar ais bréagach.

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;
};


Anois go bhfuil gach rud go breá, is cosúil go bhfuil an réiteach is fearr. Ach cé is féidir a ráthú gur ordaíodh an t-eagar?

Cad ansin?

Ar an gcéad amharc, d'fhéadfaimis an t-eagar a ordú ar dtús agus ansin an réiteach thuas a úsáid. Ach conas a rachaidh sé seo i bhfeidhm ar an am forghníomhaithe?

Is é an t-algartam is fearr quicksort le castacht ama O (Nlog (N)). Má úsáidimid é inár réiteach is fearr, athróidh sé a fheidhmíocht ó O(N) go O(Nlog(N)). An féidir teacht ar réiteach líneach le eagar neamhordúil?

4 Réiteach

Castacht ama: O(N).
Castacht spáis: O(N).

Sea, tá réiteach líneach ann; chun é seo a dhéanamh, ní mór dúinn eagar nua a chruthú ina mbeidh an liosta cluichí atá á lorg againn. Is mó úsáide cuimhne atá sa chomhbhabhtáil anseo: is é an t-aon réiteach sa pháipéar a bhfuil castacht spáis níos mó ná O(1).

Más é 1 an chéad luach d'eagar tugtha agus más é 8 an luach cuardaigh, is féidir linn an luach 7 a chur leis an eagar "luachanna cuardaigh".

Ansin, agus muid ag próiseáil gach eilimint den eagar, is féidir linn an raon “luachanna cuardaigh” a sheiceáil agus féachaint an bhfuil ceann acu cothrom lenár luach. Má tá, fill ar ais fíor.

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;
};

Is é bunús an réitigh ná lúb le haghaidh, a bhfuil, mar a chonaic muid thuas, castacht ama líneach O(N).

Is é an dara cuid atriallach dár bhfeidhm ná Array.prototype.include(), modh JavaScript a fhillfidh fíor nó bréagach ag brath ar cibé an bhfuil an luach tugtha san eagar.

Chun castacht ama Array.prototype.includes() a dhéanamh amach, is féidir linn breathnú ar an polyfill a sholáthraíonn MDN (agus scríofa i JavaScript) nó úsáid a bhaint as modh i gcód foinse inneall JavaScript mar 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;
    }
  });
}

Anseo is é an chuid atriallach de Array.prototype.include() an lúb fad i gcéim 7 a thrasnaíonn (beagnach) fad iomlán an eagar a thugtar. Ciallaíonn sé seo go bhfuil a chastacht ama líneach freisin. Bhuel, ós rud é go bhfuil sé i gcónaí céim amháin taobh thiar dár bpríomh-eagar, is é O (N + (N - 1)) an chastacht ama. Trí Nodaireacht O Mór a úsáid, déanaimid é a shimpliú go dtí O(N) - toisc gurb é N a mbíonn an tionchar is mó aige agus an méid ionchuir á mhéadú.

Maidir le castacht spásúlachta, tá gá le sraith bhreise a bhfuil a fhad scáthánú ar an eagar bunaidh (lúide a haon, tá, ach is féidir neamhaird a dhéanamh air sin), rud a fhágann castacht spáis O(N). Bhuel, cinntíonn úsáid mhéadaithe cuimhne éifeachtacht uasta an algartam.


Tá súil agam go bhfaighidh tú an t-alt úsáideach mar fhorlíonadh le d'agallamh físeáin. Léiríonn sé gur féidir fadhb shimplí a réiteach ar bhealaí éagsúla le méideanna éagsúla acmhainní a úsáid (am, cuimhne).

Molann Skillbox:

Foinse: will.com

Add a comment