በጃቫስክሪፕት ዹጎግል ቃለ መጠይቅ ቜግር መፍታት፡ 4 ዚተለያዩ መንገዶቜ

በጃቫስክሪፕት ዹጎግል ቃለ መጠይቅ ቜግር መፍታት፡ 4 ዚተለያዩ መንገዶቜ

ዚአልጎሪዝም አፈጻጞምን ሳጠና ይህን አጋጥሞኝ ነበር። ይህ ዹጎግል አስመሳይ ቃለ መጠይቅ ቪዲዮ ነው።. በትልልቅ ዹቮክኖሎጂ ኮርፖሬሜኖቜ ውስጥ ቃለ-መጠይቆቜ እንዎት እንደሚካሄዱ ሀሳብን ብቻ ሳይሆን ዚአልጎሪዝም ቜግሮቜ በተቻለ መጠን በብቃት እንዎት እንደሚፈቱ እንዲገነዘቡ ያስቜልዎታል።

ይህ ጜሑፍ ኚቪዲዮው ጋር አብሮ ዚሚሄድ አይነት ነው። በእሱ ውስጥ በሁሉም ዚሚታዩ መፍትሄዎቜ ላይ አስተያዚቶቜን አቀርባለሁ, በተጚማሪም ዚራሎን ዚመፍትሄው እትም በጃቫ ስክሪፕት. ዚእያንዳንዱ አልጎሪዝም ልዩነቶቜም ተብራርተዋል.

እኛ እናስታውስዎታለን- ለሁሉም ዹ "ሀብር" አንባቢዎቜ - ዹ "Habr" ዚማስተዋወቂያ ኮድን በመጠቀም በማንኛውም ዹ Skillbox ኮርስ ውስጥ ሲመዘገቡ ዹ 10 ሩብልስ ቅናሜ.

Skillbox ይመክራል፡ ተግባራዊ ኮርስ "ሞባይል ገንቢ PRO".

ዚቜግሩ ቀመር

ዚታዘዘ ድርድር እና ዹተወሰነ እሎት ተሰጥቶናል። ኚዚያም በድርድሩ ውስጥ ያሉት ዚሁለቱ ቁጥሮቜ ድምር ኹተሰጠው እሎት ጋር እኩል ሊሆን ይቜላል በሚለው ላይ በመመስሚት እውነት ወይም ሐሰት ዚሚመልስ ተግባር እንዲፈጥር ይጠዚቃል።

በሌላ አነጋገር፣ በድርድር ውስጥ ሁለት ኢንቲጀሮቜ አሉ x እና y፣ አንድ ላይ ሲደመር ኹተጠቀሰው እሎት ጋር እኩል ይሆናል?

ምሳሌ ሀ

ድርድር ኹተሰጠን [1፣ 2፣ 4፣ 9] እና እሎቱ 8 ኹሆነ ተግባሩ በውሞት ይመለሳል ምክንያቱም በድርድር ውስጥ ያሉት ሁለት ቁጥሮቜ እስኚ 8 ሊጚመሩ አይቜሉም።

ምሳሌ ለ

ነገር ግን ድርድር [1፣ 2፣ 4፣ 4] ኹሆነ እና እሎቱ 8 ኹሆነ ተግባሩ ወደ እውነት መመለስ አለበት ምክንያቱም 4 + 4 = 8።

መፍትሄ 1: ዚጭካኔ ኃይል

ዹጊዜ ውስብስብነት፡ O(N²)።
ዚቊታ ውስብስብነት፡ O(1)።

በጣም ግልጜ ዹሆነው ትርጉሙ ዚተጣመሩ ጥንድ ቀለበቶቜን መጠቀም ነው.

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

ይህ መፍትሔ ውጀታማ አይደለም ምክንያቱም በድርድር ውስጥ ያሉትን ሁሉንም ሊሆኑ ዚሚቜሉትን ዚሁለት ንጥሚ ነገሮቜ ድምርን ስለሚፈትሜ እና እያንዳንዱን ጥንድ ኢንዎክሶቜ ሁለት ጊዜ ያወዳድራል። (ለምሳሌ, i = 1 እና j = 2 ኹ i = 2 እና j = 1 ጋር ሲነጻጞር ተመሳሳይ ነው, ነገር ግን በዚህ መፍትሄ ሁለቱንም አማራጮቜ እንሞክራለን).

ምክንያቱም ዚእኛ መፍትሔ ለ loops ጥንድ ጎጆዎቜን ስለሚጠቀም፣ ኹ O(N²) ዹጊዜ ውስብስብነት ጋር ኳድራቲክ ነው።


መፍትሄ 2: ሁለትዮሜ ፍለጋ

ዹጊዜ ውስብስብነት፡ O(Nlog(N))።
ዚቊታ ውስብስብነት፡ O(1)
.

ድርድሮቜ ስለታዘዙ፣ ሁለትዮሜ ፍለጋን በመጠቀም መፍትሄ መፈለግ እንቜላለን። ይህ ለታዘዙ ድርድሮቜ በጣም ቀልጣፋው ስልተ ቀመር ነው። ዚሁለትዮሜ ፍለጋ ራሱ ዹO(ሎግ(N)) ጊዜ አለው። ሆኖም ግን፣ አሁንም እያንዳንዱን ንጥሚ ነገር ኚሌሎቜ እሎቶቜ ጋር ለመፈተሜ ለ loop መጠቀም ያስፈልግዎታል።

መፍትሄው ምን እንደሚመስል እነሆ። ነገሮቜን ግልጜ ለማድሚግ፣ ሁለትዮሜ ፍለጋን ለመቆጣጠር ዹተለዹ ተግባር እንጠቀማለን። እና እንዲሁም ዚማስወገድ ኢንዎክስ() ተግባር፣ ኹተሰጠው ኢንዎክስ ሲቀነስ ዚድርድርውን እትም ይመልሳል።

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

አልጎሪዝም ኹመሹጃ ጠቋሚ [0] ይጀምራል። ኚዚያም ዚመጀመሪያውን ኢንዎክስ ሳይጚምር ዚድርድር ሥሪት ይፈጥራል እና ዹተፈለገውን ድምር ለማምሚት ቀሪዎቹ እሎቶቜ ወደ ድርድር መጹመር ይቻል እንደሆነ ለማዚት ሁለትዮሜ ፍለጋን ይጠቀማል። ይህ እርምጃ በድርድር ውስጥ ላለው እያንዳንዱ አካል አንድ ጊዜ ይኚናወናል።

ዹ loop ራሱ ዹO(N) ዚመስመር ጊዜ ውስብስብነት ይኖሚዋል፣ ነገር ግን በ loop ውስጥ ሁለትዮሜ ፍለጋ እናደርጋለን፣ ይህም አጠቃላይ ዹO(Nlog(N)) ውስብስብነት ይሰጣል። ይህ መፍትሔ ኚቀዳሚው ዚተሻለ ነው, ነገር ግን አሁንም ለመሻሻል ቊታ አለ.


መፍትሄ 3: ዚመስመር ጊዜ

ዹጊዜ ውስብስብነት፡ O(N)።
ዚቊታ ውስብስብነት፡ O(1)።

አሁን ድርድር መደሚደሩን በማስታወስ ቜግሩን እንፈታዋለን. መፍትሄው ሁለት ቁጥሮቜን መውሰድ ነው-አንደኛው መጀመሪያ ላይ እና አንድ መጚሚሻ። ውጀቱ ኹተፈለገው ኹተለዹ, ኚዚያም ዚመነሻ እና ዚመጚሚሻ ነጥቊቹን ይቀይሩ.

ውሎ አድሮ ወይ ዹምንፈልገውን እሎት አጋጥሞን ወደ እውነት እንመለሳለን፣ አለዚያ መነሻ እና መድሚሻ ነጥቊቜ ተገናኝተው በውሞት ይመለሳሉ።

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


አሁን ሁሉም ነገር ጥሩ ነው, መፍትሄው በጣም ጥሩ ይመስላል. ነገር ግን ድርድር መያዙን ማን ዋስትና ይሰጣል?

እንግዲህ ምን አለ?

በመጀመሪያ በጚሚፍታ ፣ እኛ በቀላሉ ድርድር መጀመሪያ ማዘዝ እና ኚዚያ በላይ ያለውን መፍትሄ ልንጠቀም እንቜላለን። ግን ይህ በአፈፃፀም ጊዜ ላይ ምን ተጜዕኖ ይኖሹዋል?

በጣም ጥሩው አልጎሪዝም በጊዜ ውስብስብነት O (Nlog (N)) ፈጣን ድርድር ነው። በእኛ ምርጥ መፍትሄ ኚተጠቀምንበት አፈፃፀሙን ኹኩ(N) ወደ ኩ(Nlog(N)) ይቀይራል። ካልታዘዘ ድርድር ጋር መስመራዊ መፍትሄ ማግኘት ይቻላል?

ዹ 4 መፍትሄ

ዹጊዜ ውስብስብነት፡ O(N)።
ዚቊታ ውስብስብነት፡ O(N)

አዎ፣ መስመራዊ መፍትሄ አለፀ ይህንን ለማድሚግ ዹምንፈልገውን ዚተዛማጆቜ ዝርዝር ዚያዘ አዲስ አደራደር መፍጠር አለብን። እዚህ ያለው ዚንግድ ልውውጥ ዹበለጠ ዹማህደሹ ትውስታ አጠቃቀም ነው፡ ኹኩ(1) ዚሚበልጥ ዚቊታ ውስብስብነት ያለው ወሚቀት ውስጥ ያለው ብ቞ኛው መፍትሄ ነው።

ዚአንድ ዹተሰጠ ድርድር ዚመጀመሪያ ዋጋ 1 ኹሆነ እና ዹፍለጋ ዋጋው 8 ኹሆነ, እሎቱን 7 ወደ "ዹፍለጋ እሎቶቜ" ድርድር ማኹል እንቜላለን.

ኚዚያም፣ እያንዳንዱን ዚድርድር አካል ስናስኬድ፣ “ዹፍለጋ እሎቶቜን” ድርድር ማሚጋገጥ እና ኚመካኚላ቞ው አንዱ ኹኛ ዋጋ ጋር እኩል መሆኑን ማዚት እንቜላለን። አዎ ኚሆነ፣ እውነትን ተመለስ።

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

ዚመፍትሄው መሰሚት ለ loop ነው, እሱም ኹላይ እንዳዚነው, ዹ O (N) ዚመስመር ጊዜ ውስብስብነት አለው.

ሁለተኛው ዚተግባራቜን ተደጋጋሚ ክፍል Array.prototype.include() ነው፣ ዚጃቫ ስክሪፕት ዘዮ ድርድር ዹተሰጠውን እሎት እንደያዘው ላይ በመመስሚት እውነት ወይም ሀሰት ዚሚመለስ ነው።

ዹ Array.prototype.includes()ን ዹጊዜ ውስብስብነት ለማወቅ በኀምዲኀን ዹቀሹበውን (እና በጃቫስክሪፕት ዚተጻፈውን) ፖሊፊል ማዚት እንቜላለን ወይም በጃቫ ስክሪፕት ሞተር ምንጭ ኮድ እንደ 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;
    }
  });
}

እዚህ ላይ ዹ Array.prototype.include() ተደጋጋሚ ክፍል በደሹጃ 7 ላይ ያለው ዹጊዜ ዑደት ነው (ኹሞላ ጎደል) ዹተሰጠውን ድርድር ሙሉውን ርዝመት ዚሚያልፍ። ይህ ማለት ዹጊዜ ውስብስብነቱም መስመራዊ ነው። ደህና፣ ሁልጊዜ ኹዋናው ድርደራቜን አንድ እርምጃ በኋላ ስለሆነ፣ ዹጊዜ ውስብስብነቱ O (N + (N - 1)) ነው። ቢግ ኩ ኖ቎ሜን በመጠቀም፣ ወደ O(N) እናቀላለን - ምክንያቱም ዚግብአት መጠኑን ሲጚምር ትልቁ ተጜእኖ ያለው N ነው።

ዚቊታ ውስብስብነትን በተመለኚተ፣ ርዝመቱ ዚመጀመሪያውን ድርድር ዚሚያንጞባርቅ ተጚማሪ ድርድር ያስፈልጋል (አንድ ሲቀነስ አዎ፣ ግን ቜላ ሊባል ይቜላል) ይህም ዹ O(N) ዚቊታ ውስብስብነት ያስኚትላል። ደህና ፣ ዹማህደሹ ትውስታ አጠቃቀም ኹፍተኛውን ዚአልጎሪዝም ውጀታማነት ያሚጋግጣል።


ጜሑፉ ለቪዲዮ ቃለ መጠይቁ እንደ ማሟያ ጠቃሚ ሆኖ እንዳገኙት ተስፋ አደርጋለሁ። ቀላል ቜግር በተለያዩ መንገዶቜ በተለያዚ መጠን ጥቅም ላይ ዹዋለ (ጊዜ, ማህደሹ ትውስታ) በመጠቀም መፍታት እንደሚቻል ያሳያል.

Skillbox ይመክራል፡

ምንጭ: hab.com

አስተያዚት ያክሉ