সংখ্যার বাছাই করা অ্যারেতে কোনও সংখ্যা প্রবেশের কার্যকর উপায়?


142

আমার একটি বাছাই করা জাভাস্ক্রিপ্ট অ্যারে রয়েছে এবং অ্যারেতে আরও একটি আইটেম সন্নিবেশ করতে চাই যেমন ফলাফলযুক্ত অ্যারে বাছাই করা থাকে। আমি অবশ্যই একটি সাধারণ কুইকোর্ট-স্টাইল সন্নিবেশ ফাংশনটি বাস্তবায়িত করতে পারি:

var array = [1,2,3,4,5,6,7,8,9];
var element = 3.5;
function insert(element, array) {
  array.splice(locationOf(element, array) + 1, 0, element);
  return array;
}

function locationOf(element, array, start, end) {
  start = start || 0;
  end = end || array.length;
  var pivot = parseInt(start + (end - start) / 2, 10);
  if (end-start <= 1 || array[pivot] === element) return pivot;
  if (array[pivot] < element) {
    return locationOf(element, array, pivot, end);
  } else {
    return locationOf(element, array, start, pivot);
  }
}

console.log(insert(element, array));

[সতর্কতা] অ্যারের শুরুতে সন্নিবেশ করানোর চেষ্টা করার সময় এই কোডটিতে একটি ত্রুটি রয়েছে, উদাহরণস্বরূপ insert(2, [3, 7 ,9]) ভুল উত্পাদন করে [3, 2, 7, 9]।

তবে, আমি লক্ষ করেছি যে অ্যারে.সোর্ট ফাংশনের বাস্তবায়ন সম্ভবত আমার জন্য এবং নেটিভভাবে এটি করতে পারে:

var array = [1,2,3,4,5,6,7,8,9];
var element = 3.5;
function insert(element, array) {
  array.push(element);
  array.sort(function(a, b) {
    return a - b;
  });
  return array;
}

console.log(insert(element, array));

দ্বিতীয়টির চেয়ে প্রথম বাস্তবায়নটি বেছে নেওয়ার কোনও ভাল কারণ আছে কি?

সম্পাদনা : নোট করুন যে সাধারণ ক্ষেত্রে, একটি ও (লগ (এন)) সন্নিবেশ (প্রথম উদাহরণ হিসাবে প্রয়োগ করা হয়) জেনেরিক বাছাইকরণ অ্যালগরিদমের তুলনায় দ্রুত হবে; তবে এটি বিশেষত জাভাস্ক্রিপ্টের ক্ষেত্রে প্রয়োজন হয় না। মনে রাখবেন যে:

  • বেশ কয়েকটি সন্নিবেশ অ্যালগোরিদমের জন্য সর্বোত্তম কেস হল ও (এন), যা এখনও ও (লগ (এন)) থেকে উল্লেখযোগ্যভাবে পৃথক, তবে ও (এন লগ (এন)) এর মতো নীচে উল্লিখিত হিসাবে খারাপ নয়। এটি ব্যবহৃত নির্দিষ্ট বাছাই করা অ্যালগরিদমে নেমে আসবে ( জাভাস্ক্রিপ্ট অ্যারে.সোর্ট বাস্তবায়ন দেখুন? )
  • জাভাস্ক্রিপ্টে বাছাইয়ের পদ্ধতিটি একটি দেশীয় ফাংশন, সুতরাং সম্ভাব্য আকারে বিশাল সুবিধাগুলি উপলব্ধি করতে - ও (লগ (এন)) যুক্তিযুক্ত আকারের ডেটা সেটগুলির জন্য ও (এন) এর চেয়ে আরও খারাপ হতে পারে।

দ্বিতীয় বাস্তবায়নে স্প্লাইস ব্যবহার করা কিছুটা ব্যর্থ। ধাক্কা ব্যবহার করবেন না কেন?
ব্রেটন

ভালো কথা, আমি প্রথম থেকে এটি অনুলিপি করেছি।
এলিয়ট ক্রু

4
যে কোনও কিছু splice()(যেমন আপনার প্রথম উদাহরণ) ইতিমধ্যে ও (এন)। এমনকি যদি এটি অভ্যন্তরীণভাবে পুরো অ্যারেটির একটি নতুন অনুলিপি তৈরি না করে, তবে উপাদানটি পজিশনে inোকাতে হলে এটি সমস্ত n আইটেমকে 1 পজিশন ফিরিয়ে রাখতে হবে সম্ভবত এটি দ্রুত কারণ এটি একটি নেটিভ ফাংশন এবং ধ্রুবকটি রয়েছে কম, তবে এটি ও (এন) তবে।
j_random_hacker

6
এছাড়াও, এই কোডটি ব্যবহার করে লোকেদের ভবিষ্যতের রেফারেন্সের জন্য, অ্যারের শুরুতে sertোকানোর চেষ্টা করার সময় কোডটিতে একটি বাগ রয়েছে g সংশোধিত কোডের জন্য আরও নীচে দেখুন।
পিনোচিও

3
ব্যবহার করবেন না parseIntব্যবহার Math.floorপরিবর্তে। Math.floorএর চেয়ে অনেক বেশি দ্রুত parseInt: jsperf.com/test-parseint-and-math-floor
হুবার্ট শ্যালনাস্ট

উত্তর:


58

একটি একক ডেটা পয়েন্ট হিসাবে, কিক্সের জন্য আমি এটি পরীক্ষা করেছিলাম উইন্ডোজ Chrome এ ক্রোম ব্যবহার করে দুটি পদ্ধতি ব্যবহার করে ১০০০০০ প্রাক-সাজানো সংখ্যার একটি অ্যারেতে এলোমেলো উপাদানগুলিকে 1000,000 এন্ডার্ড সন্নিবেশ করিয়েছি:

First Method:
~54 milliseconds
Second Method:
~57 seconds

সুতরাং, অন্ততপক্ষে এই সেটআপে নেটিভ পদ্ধতিটি এটি তৈরি করে না। এমনকি ছোট ডেটা সেটগুলির ক্ষেত্রেও এটি সত্য, 1000 টি অ্যারেতে 100 টি উপাদান সন্নিবেশ করানো:

First Method:
1 milliseconds
Second Method:
34 milliseconds

1
arrays.sort বেশ ভয়ঙ্কর মনে হচ্ছে
njzk2

2
দেখে মনে হচ্ছে যে অ্যারে.স্প্লাইস অবশ্যই 54 টি মাইক্রোসেকেন্ডের মধ্যে একটি একক উপাদান সন্নিবেশ করানোর জন্য অবশ্যই খুব চালাক কিছু করছে।
gnasher729

@ gnasher729 - আমি মনে করি না যে জাভাস্ক্রিপ্ট অ্যারেগুলি শারীরিকভাবে ক্রমাগত অ্যারেগুলির মতো একই সি হিসাবে রয়েছে। আমি মনে করি জেএস ইঞ্জিনগুলি এগুলিকে একটি হ্যাশ মানচিত্র / অভিধান হিসাবে দ্রুত সন্নিবেশ সক্ষম করতে সক্ষম করতে পারে।
ইয়ান

1
আপনি যখন তুলনামূলক ফাংশনটি ব্যবহার করেন Array.prototype.sort, আপনি সি ++ এর সুবিধা হারাবেন কারণ জেএস ফাংশনটিকে এত বেশি বলা হয় called
অ্যালেকারসন

ক্রোম টিমসোর্ট ব্যবহার করে এখন প্রথম পদ্ধতিটি কীভাবে তুলনা করে ? টিমসোর্ট উইকিপিডিয়া থেকে : "ইনপুটটি ইতিমধ্যে বাছাই করা হলে সবচেয়ে ভাল ক্ষেত্রে, [টিমসোর্ট] রৈখিক সময়ে চলে"।
poshest

47

সাধারণ ( ডেমো ):

function sortedIndex(array, value) {
    var low = 0,
        high = array.length;

    while (low < high) {
        var mid = (low + high) >>> 1;
        if (array[mid] < value) low = mid + 1;
        else high = mid;
    }
    return low;
}

4
চমৎকার স্পর্শ. আমি কখনও কখনও দুটি সংখ্যার মধ্যমান খুঁজে পাওয়ার জন্য বিটওয়াইজ অপারেটরগুলি ব্যবহার করার কথা শুনিনি। সাধারণত আমি কেবল ০.০ দিয়ে গুণ করব। এই উপায়ে এটি করার কোনও উল্লেখযোগ্য পারফরম্যান্স রয়েছে?
জ্যাকসন

2
@ জ্যাকসন x >>> 1বাইনারি রাইট শিফটটি 1 পজিশনে, যা কার্যকরভাবে মাত্র 2 দ্বারা বিভাজন 1011- উদাহরণস্বরূপ 11: -> 101ফলাফল 5
পৌঁছেছে

3
ইতিমধ্যে এই ট্র্যাক উপর @Qwerty @Web_Designer বিয়িং, আপনি মধ্যে পার্থক্য ব্যাখ্যা হতে পারে >>> 1এবং ( দেখা এখানে এবং সেখানে ) >> 1?
ইয়্যাকার্ট

4
>>>একটি স্বাক্ষরবিহীন ডান শিফট, যেখানে >>সাইন-প্রসারিত - এটি সমস্তই নেতিবাচক সংখ্যার ইন-মেমরি উপস্থাপনায় ফোটে, যেখানে bitণাত্মক হলে উচ্চ বিট সেট করা হয়। সুতরাং আপনি যদি 0b1000ঠিক 1 স্থান স্থানান্তরিত করেন তবে আপনি >>পাবেন 0b1100যদি আপনি পরিবর্তে ব্যবহার করেন তবে >>>পাবেন 0b0100। উত্তরে দেওয়া ক্ষেত্রে এটি সত্যিকার অর্থে গুরুত্বপূর্ণ নয় (সংখ্যাটি স্বাক্ষরিত 32-বিট পজিটিভ পূর্ণসংখ্যার সর্বোচ্চ মান বা negativeণাত্মক চেয়ে বেশি হওয়া উচিত নয়), তবে এই দুটি ক্ষেত্রে সঠিক ব্যবহার করা গুরুত্বপূর্ণ (আপনি আপনার কোন মামলাটি পরিচালনা করা দরকার তা চয়ন করতে হবে)।
আশেরকিন

2
@ আশেরকিন - এটি সঠিক নয়: "আপনি যদি 0b1000ঠিক 1 স্থান স্থান পরিবর্তন করেন তবে আপনি >>পাবেন 0b1100"। না, আপনি পেতে 0b0100। বিভিন্ন ডান শিফট অপারেটরের ফলাফল negativeণাত্মক সংখ্যা এবং 2 ^ 31 এর চেয়ে বেশি সংখ্যার সংখ্যা বাদে (অর্থাত প্রথম বিটটিতে 1 এর সাথে সংখ্যা) বাদে সমস্ত মানের জন্য একই হবে।
গিলি

29

একটি খুব আকর্ষণীয় আলোচনা সহ খুব ভাল এবং অসাধারণ প্রশ্ন! আমি Array.sort()কয়েক হাজার বস্তুর সাথে একটি অ্যারেতে একক উপাদানকে চাপ দেওয়ার পরেও ফাংশনটি ব্যবহার করছিলাম ।

locationOfজটিল বস্তু থাকার কারণে আমার উদ্দেশ্যে আপনার ফাংশনটি প্রসারিত করতে হয়েছিল এবং সুতরাং এর মতো তুলনামূলক ফাংশনটির প্রয়োজন ছিল Array.sort():

function locationOf(element, array, comparer, start, end) {
    if (array.length === 0)
        return -1;

    start = start || 0;
    end = end || array.length;
    var pivot = (start + end) >> 1;  // should be faster than dividing by 2

    var c = comparer(element, array[pivot]);
    if (end - start <= 1) return c == -1 ? pivot - 1 : pivot;

    switch (c) {
        case -1: return locationOf(element, array, comparer, start, pivot);
        case 0: return pivot;
        case 1: return locationOf(element, array, comparer, pivot, end);
    };
};

// sample for objects like {lastName: 'Miller', ...}
var patientCompare = function (a, b) {
    if (a.lastName < b.lastName) return -1;
    if (a.lastName > b.lastName) return 1;
    return 0;
};

7
রেকর্ডটির জন্য এটি লক্ষ্য করার মতো মনে হয় যে অ্যারের শুরুতে versionোকানোর চেষ্টা করার সময় এই সংস্করণটি সঠিকভাবে কাজ করে। (এটি উল্লেখ করার মতো কারণ মূল প্রশ্নের সংস্করণটিতে একটি ত্রুটি রয়েছে এবং সে ক্ষেত্রে সঠিকভাবে কাজ করে না))
গ্যারিওব

3
আমার বাস্তবায়ন আলাদা ছিল কিনা তা আমি নিশ্চিত নই, তবে return c == -1 ? pivot : pivot + 1;সঠিক সূচীটি ফেরত দেওয়ার জন্য আমার বার্ষিকী পরিবর্তন করতে হবে । অন্যথায় 1 দৈর্ঘ্যের অ্যারের জন্য ফাংশনটি -1 বা 0 ফিরে আসবে
নিল

3
@ জেমস: পরামিতিগুলি শুরু এবং শেষ কেবল পুনরাবৃত্ত কলগুলিতে ব্যবহৃত হয় এবং ইনিটাল কলটিতে ব্যবহৃত হবে না। এগুলি অ্যারের সূচক মান হিসাবে এগুলি অবশ্যই সংখ্যার টাইপ হতে হবে এবং পুনরাবৃত্ত কল এ এটিকে স্পষ্টতই দেওয়া হয় is
kwrl

1
@ দ্য রিডপিয়ার: না, আমার অর্থ ছিল >> 1দ্রুত (বা ধীর নয়) হওয়া উচিত/ 2
কেআরআরএল

1
comparerফাংশনের ফলাফল সহ আমি একটি সম্ভাব্য সমস্যা দেখতে পাচ্ছি । এই অ্যালগরিদমে এটির সাথে তুলনা করা +-1হলেও এটি নির্বিচার মান <0/ হতে পারে >0তুলনা ফাংশন দেখুন । সমস্যাযুক্ত অংশটি কেবল switchবিবৃতি নয় লাইনও: if (end - start <= 1) return c == -1 ? pivot - 1 : pivot;যেখানে পাশাপাশি cতুলনা করা -1হয়।
এক্সএভিয়ার

19

আপনার কোডে একটি বাগ আছে। এটি পড়া উচিত:

function locationOf(element, array, start, end) {
  start = start || 0;
  end = end || array.length;
  var pivot = parseInt(start + (end - start) / 2, 10);
  if (array[pivot] === element) return pivot;
  if (end - start <= 1)
    return array[pivot] > element ? pivot - 1 : pivot;
  if (array[pivot] < element) {
    return locationOf(element, array, pivot, end);
  } else {
    return locationOf(element, array, start, pivot);
  }
}

এই ফিক্স ব্যতীত কোড কখনই অ্যারের শুরুতে কোনও উপাদান sertোকাতে সক্ষম হবে না।


আপনি কেন 0 বা একটি int- ইন করছেন? অর্থাত্ কি শুরু হয় || 0 করেন?
পিনোচিও

3
@ পিনোকিও: শুরু || 0 এর সংক্ষিপ্ত সমতুল্য: যদি (! প্রারম্ভ) শুরু = 0; - তবে, "দীর্ঘতর" সংস্করণটি আরও কার্যকরী, কারণ এটি নিজের কাছে কোনও ভেরিয়েবল বরাদ্দ করে না।
সুপারনাভা

11

আমি জানি এটি একটি পুরানো প্রশ্ন যা ইতিমধ্যে উত্তর পেয়েছে এবং এখানে আরও বেশ কিছু শালীন উত্তর রয়েছে। আমি কিছু উত্তর দেখতে পাচ্ছি যাতে প্রস্তাব দেওয়া হয় যে আপনি ও (লগ এন) এর সঠিক সন্নিবেশ সূচীটি অনুসন্ধান করে এই সমস্যাটি সমাধান করতে পারেন - আপনি পারবেন তবে আপনি সেই সময়টি সন্নিবেশ করতে পারবেন না কারণ অ্যারেটি তৈরি করতে আংশিকভাবে অনুলিপি করা দরকার স্থান।

নীচের লাইন: যদি আপনার সত্যই ও (লগ এন) স্র্ট করা অ্যারেতে সন্নিবেশ করা এবং মুছে ফেলা দরকার হয় তবে আপনার আলাদা ডেটা কাঠামো দরকার - অ্যারে নয়। আপনার একটি বি-ট্রি ব্যবহার করা উচিত । একটি বৃহত ডেটা সেট জন্য একটি বি-ট্রি ব্যবহার করে আপনি যে পারফরম্যান্স লাভ পাবেন তা এখানে প্রদত্ত যে কোনও উন্নতি বামন করবে।

যদি আপনার অবশ্যই একটি অ্যারে ব্যবহার করা হয়। আমি সন্নিবেশ সাজানোর উপর ভিত্তি করে নীচের কোডটি অফার করছি, যা কাজ করে, যদি এবং কেবল অ্যারে ইতিমধ্যে সাজানো থাকে তবে। আপনার প্রতিটি সন্নিবেশের পরে যখন রিসর্ট করা দরকার তখন এটি ক্ষেত্রে কার্যকর হয়:

function addAndSort(arr, val) {
    arr.push(val);
    for (i = arr.length - 1; i > 0 && arr[i] < arr[i-1]; i--) {
        var tmp = arr[i];
        arr[i] = arr[i-1];
        arr[i-1] = tmp;
    }
    return arr;
}

এটি ও (এন) এ পরিচালনা করা উচিত যা আমি মনে করি আপনি সবচেয়ে ভাল করতে পারেন। জেএস একাধিক অ্যাসাইনমেন্ট সমর্থন করলে ভাল হবে। এখানে খেলতে একটি উদাহরণ এখানে:

হালনাগাদ:

এটি দ্রুত হতে পারে:

function addAndSort2(arr, val) {
    arr.push(val);
    i = arr.length - 1;
    item = arr[i];
    while (i > 0 && item < arr[i-1]) {
        arr[i] = arr[i-1];
        i -= 1;
    }
    arr[i] = item;
    return arr;
}

জেএস বিন লিঙ্ক আপডেট হয়েছে


জাভাস্ক্রিপ্টে সন্নিবেশ সাজানোর প্রস্তাব আপনি বাইনারি অনুসন্ধান এবং স্প্লাইস পদ্ধতির চেয়ে ধীর হবে কারণ স্প্লাইসটির দ্রুত বাস্তবায়ন রয়েছে।
ট্রিনকোট

জাভাস্ক্রিপ্ট যদি না কোনওভাবে জটিলতার আইনগুলিকে ভেঙে ফেলতে পারে তবে আমি সন্দেহবাদী। বাইনারি অনুসন্ধান এবং স্প্লাইস পদ্ধতিটি কীভাবে দ্রুত হয় তার কী আপনার চলমান উদাহরণ রয়েছে?
ডোমারিগেটো

আমি আমার দ্বিতীয় মন্তব্যটি প্রত্যাহার করি ;-) প্রকৃতপক্ষে, একটি অ্যারে আকার থাকবে যার বাইরে একটি বি-ট্রি সমাধান বিচ্ছিন্ন দ্রবণটি ছাড়িয়ে যাবে।
ট্রিনকোট

9

আপনার সন্নিবেশ ফাংশন ধরে নেয় যে প্রদত্ত অ্যারে বাছাই করা হয়েছে, এটি সরাসরি অনুসন্ধান করতে পারে যেখানে নতুন উপাদানটি সন্নিবেশ করা যায়, সাধারণত অ্যারের কয়েকটি উপাদান দেখে।

একটি অ্যারের সাধারণ সাজানোর কাজটি এই শর্টকাটগুলি নিতে পারে না। স্পষ্টতই এটিকে কমপক্ষে অ্যারেতে থাকা সমস্ত উপাদানগুলি আগে থেকেই সঠিকভাবে অর্ডার করা হয়েছে কিনা তা পরীক্ষা করে দেখতে হবে। এই ফ্যাক্টটি একাই সাধারণ সাজানোর সন্নিবেশ ফাংশন থেকে ধীর করে তোলে।

একটি জেনেরিক সাজানোর আলগোরিদিম সাধারণত গড়ে হে (ঢ ⋅ লগ (ঢ)) এবং বাস্তবায়ন এটি আসলে সবচেয়ে খারাপ ক্ষেত্রে হতে পারে যদি অ্যারের ইতিমধ্যে অনুসারে বাছাই করা হয় উপর নির্ভর করে, জটিলতার নেতৃস্থানীয় হে (ঢ 2 ) । এর পরিবর্তে সরাসরি সন্নিবেশের অবস্থানটি অনুসন্ধান করতে ও (লগ (এন)) এর একটি জটিলতা রয়েছে , তাই এটি সর্বদা আরও দ্রুত হবে।


এটি লক্ষণীয় যে অ্যারেতে কোনও উপাদান সন্নিবেশ করাতে ও (এন) এর জটিলতা রয়েছে, সুতরাং শেষ ফলাফলটি একই রকম হওয়া উচিত।
নেমপ্লেয়ার

5

অল্প সংখ্যক আইটেমের জন্য পার্থক্যটি বেশ তুচ্ছ। তবে, যদি আপনি প্রচুর আইটেম সন্নিবেশ করিয়ে থাকেন বা খুব বড় অ্যারে দিয়ে কাজ করছেন, প্রতিটি সন্নিবেশের পরে .sort () কল করুন যদি প্রচুর পরিমাণে ওভারহেড তৈরি করে।

আমি এই সঠিক উদ্দেশ্যে একটি চমত্কার চতুর বাইনারি অনুসন্ধান / সন্নিবেশ ফাংশন লিখতে শেষ করেছি, তাই আমি ভেবেছিলাম আমি এটি ভাগ করব। যেহেতু এটি whileপুনরাবৃত্তির পরিবর্তে একটি লুপ ব্যবহার করে, অতিরিক্ত ফাংশন কলগুলির জন্য কোনও শুনানি নেই, তাই আমি মনে করি মূলত পোস্ট করা পদ্ধতিরগুলির চেয়ে পারফরম্যান্স আরও ভাল হবে। এবং এটি ডিফল্টরূপে ডিফল্ট তুলকটি এমুলেট করে Array.sort()তবে পছন্দসই হলে একটি পছন্দসই তুলনামূলক ফাংশন গ্রহণ করে।

function insertSorted(arr, item, comparator) {
    if (comparator == null) {
        // emulate the default Array.sort() comparator
        comparator = function(a, b) {
            if (typeof a !== 'string') a = String(a);
            if (typeof b !== 'string') b = String(b);
            return (a > b ? 1 : (a < b ? -1 : 0));
        };
    }

    // get the index we need to insert the item at
    var min = 0;
    var max = arr.length;
    var index = Math.floor((min + max) / 2);
    while (max > min) {
        if (comparator(item, arr[index]) < 0) {
            max = index;
        } else {
            min = index + 1;
        }
        index = Math.floor((min + max) / 2);
    }

    // insert the item
    arr.splice(index, 0, item);
};

আপনি যদি অন্য লাইব্রেরি ব্যবহারের জন্য উন্মুক্ত হন তবে লড্যাশটি सॉ োর্টড ইন্ডেক্স এবং সোর্টার্ড লাস্ট ইনডেক্স ফাংশন সরবরাহ করে, যা whileলুপের জায়গায় ব্যবহার করা যেতে পারে । দুটি সম্ভাব্য ডাউনসাইড হ'ল 1) পারফরম্যান্স আমার পদ্ধতির মতো তত ভাল নয় (ভেবেছি এটি কতটা খারাপ তা আমি নিশ্চিত নই) এবং 2) এটি কোনও কাস্টম তুলনামূলক ফাংশন গ্রহণ করে না, তুলনা করার মান পাওয়ার জন্য কেবল একটি পদ্ধতি (ডিফল্ট তুলনামূলক ব্যবহার করে, আমি ধরে নিই)


কলটি arr.splice()হ'ল ও (এন) সময়ের জটিলতা।
ডোমারিগিয়েটো

4

এখানে কয়েকটি চিন্তাভাবনা রয়েছে: প্রথমত, আপনি যদি আপনার কোডটির রানটাইম সম্পর্কে সত্যই উদ্বিগ্ন হন, আপনি বিল্ট-ইন ফাংশনগুলিতে কল করলে কী ঘটে তা অবশ্যই নিশ্চিত হন! আমি জাভাস্ক্রিপ্ট নিচে থেকে উঠে জানি না, কিন্তু সংযুক্ত করান ফাংশনের একটি দ্রুত গুগল ফিরে এই , যা নির্দেশ করে আপনি একটি সম্পূর্ণ নতুন অ্যারে প্রতিটি কলের তৈরি করছেন বলে মনে হয়! আমি জানি না এটি আসলে গুরুত্বপূর্ণ কিনা তবে এটি অবশ্যই দক্ষতার সাথে সম্পর্কিত। আমি দেখতে পাই যে ব্রেটান, মন্তব্যগুলিতে ইতিমধ্যে এটি চিহ্নিত করেছে, তবে এটি অবশ্যই আপনার পছন্দসই অ্যারে-ম্যানিপুলেটিং ফাংশনটির জন্য ধারণ করে।

যাইহোক, আসলে সমস্যা সমাধানের দিকে।

যখন আমি পড়লাম যে আপনি বাছাই করতে চেয়েছিলেন, আমার প্রথম চিন্তাটি সন্নিবেশ সারণি ব্যবহার করা হয় ! । এটা তোলে কুশলী কারণ এটা রৈখিক সময় রান উপর সাজানো, বা প্রায়-অনুসারে সাজানো তালিকা । আপনার অ্যারেগুলিতে কেবলমাত্র 1 টি উপাদান থাকবে না, যা প্রায় সাজানো হিসাবে গণনা করা হয় (2, 3 আকারের অ্যারেগুলি বা যা কিছু হোক না কেন, তবে সেই পরিমাণে)। এখন, বাছাইটি বাস্তবায়ন খুব খারাপ নয়, তবে এটি এমন একটি ঝামেলা যা আপনি মোকাবেলা করতে নাও চান, এবং আবারও, আমি জাভাস্ক্রিপ্ট সম্পর্কে একটি জিনিস জানি না এবং যদি এটি সহজ বা শক্ত বা কী হবে না। এটি আপনার অনুসন্ধানের ক্রিয়াকলাপের প্রয়োজনীয়তা সরিয়ে দেয় এবং আপনি কেবল ধাক্কা দেন (ব্রেটনের পরামর্শ অনুসারে)।

দ্বিতীয়ত, আপনার "কুইকোর্ট-এস্কু" লুকিং ফাংশনটি বাইনারি অনুসন্ধানের অ্যালগরিদম বলে মনে হচ্ছে ! এটি একটি খুব সুন্দর অ্যালগরিদম, স্বজ্ঞাত এবং দ্রুত, তবে একটি ধরা সহ: এটি সঠিকভাবে প্রয়োগ করা কুখ্যাতভাবে কঠিন। আপনার ঠিক আছে কিনা তা আমি বলার সাহস করব না (আমি আশা করি এটি অবশ্যই! :)) তবে আপনি যদি এটি ব্যবহার করতে চান তবে সাবধান হন।

যাইহোক, সংক্ষিপ্তসার: সন্নিবেশ বাছাইয়ের সাথে "পুশ" ব্যবহার করা লিনিয়ার সময়ে (বাকি অ্যারেটি সাজানো ধরে নেওয়া) কাজ করবে এবং কোনও অগোছালো বাইনারি অনুসন্ধান অ্যালগরিদম প্রয়োজনীয়তা এড়াবে। আমি জানি না এটি সবচেয়ে ভাল উপায় কিনা (অ্যারেগুলির অন্তর্নিহিত বাস্তবায়ন, সম্ভবত একটি পাগল অন্তর্নির্মিত কার্য আরও ভাল করে, কে জানে) তবে এটি আমার কাছে যুক্তিসঙ্গত বলে মনে হয়। :) - আগোর।


1
+1 কারণ যে কোনও কিছু splice()ইতিমধ্যে ও (এন) রয়েছে। এমনকি যদি এটি অভ্যন্তরীণভাবে পুরো অ্যারেটির একটি নতুন অনুলিপি তৈরি না করে, তবে উপাদানটি 0 অবস্থানে
ifোকাতে

আমি বিশ্বাস করি যে সন্নিবেশ সাজানোর বিষয়টি ও (এন) সেরা কেস এবং ও (এন ^ 2) সবচেয়ে খারাপ ক্ষেত্রে (যদিও ওপি'র ব্যবহারের ক্ষেত্রে সম্ভবত সবচেয়ে ভাল ক্ষেত্রে রয়েছে)।
ডোমারিগ্যাটো

ওপিকে কথা বলার জন্য মাইনাস এক। প্রথম অনুচ্ছেদে অনুভূত উপদেশের মতো অনুভূত হয়েছিল যে টুকরো টুকরো টুকরো টুকরো টুকরো কিভাবে কাজ করে
ম্যাট জেরা

2

এটি সম্পাদন করার জন্য চারটি পৃথক পৃথক অ্যালগরিদমের তুলনা এখানে দেওয়া হয়েছে: https://jsperf.com/sorted-array-insert-compistance/1

আলগোরিদিম

  • নিষ্পাপ: কেবল ধাক্কা এবং () পরে সাজান)
  • লিনিয়ার: অ্যারের উপরে পুনরাবৃত্তি করুন এবং যেখানে উপযুক্ত সন্নিবেশ করান
  • বাইনারি অনুসন্ধান: https://stackoverflow.com/a/20352387/154329 থেকে নেওয়া
  • "দ্রুত সাজানোর মতো": সিন্থেটিজেরো থেকে পরিশোধিত সমাধান ( https://stackoverflow.com/a/18341744/154329 )

নিষ্পাপ সর্বদা ভয়ঙ্কর। এটি ছোট অ্যারের আকারের জন্য মনে হয়, অন্য তিনটি খুব বেশি পৃথক নয়, তবে বৃহত্তর অ্যারেগুলির জন্য, শেষ 2 সাধারণ রৈখিক পদ্ধতির চেয়ে বেশি কার্যকর।


দ্রুত সন্নিবেশ এবং অনুসন্ধান কার্যকর করার জন্য ডিজাইন করা ডেটা স্ট্রাকচারগুলি কেন পরীক্ষা করা হচ্ছে না? প্রাক্তন। তালিকা এবং বিএসটি ছেড়ে যান। stackoverflow.com/a/59870937/3163618
qwr

ক্রোম টিমসোর্ট ব্যবহার করে এখন কীভাবে নেটিভ তুলনা করে ? টিমসোর্ট উইকিপিডিয়া থেকে : "সবচেয়ে ভাল ক্ষেত্রে, যখন ইনপুটটি ইতিমধ্যে সাজানো হয় তখন তা লিনিয়ার সময়ে চলবে"।
poshest

2

এখানে এমন একটি সংস্করণ যা লোডাশ ব্যবহার করে।

const _ = require('lodash');
sortedArr.splice(_.sortedIndex(sortedArr,valueToInsert) ,0,valueToInsert);

দ্রষ্টব্য: सॉোর্টড ইন্ডেক্স একটি বাইনারি অনুসন্ধান করে।


1

আমি যে সর্বোত্তম ডেটা স্ট্রাকচারের কথা ভাবতে পারি তা হ'ল একটি ইনডেক্সেড স্কিপ লিস্ট যা লাইং টাইম ক্রিয়াকলাপকে সক্ষম করে এমন একটি শ্রেণিবদ্ধ কাঠামোর সাথে সংযুক্ত তালিকার সন্নিবেশ বৈশিষ্ট্যগুলি বজায় রাখে। গড়ে, অনুসন্ধান, সন্নিবেশ এবং এলোমেলো অ্যাক্সেস লকআপগুলি ও (লগ এন) সময়ে করা যেতে পারে।

একটি আদেশের পরিসংখ্যান গাছ একটি র‌্যাঙ্ক ফাংশন সহ লগ সময় সূচকে সক্ষম করে।

আপনার যদি এলোমেলো অ্যাক্সেসের প্রয়োজন না হয় তবে আপনার ও (লগ এন) সন্নিবেশ এবং কীগুলির সন্ধান প্রয়োজন, আপনি অ্যারে কাঠামোটি খনন করতে পারেন এবং যে কোনও ধরণের বাইনারি অনুসন্ধান ট্রি ব্যবহার করতে পারেন ।

array.splice()গড় ও (এন) সময় হওয়ায় যে উত্তরগুলি ব্যবহার করে সেগুলি মোটেই কার্যকর নয়। গুগল ক্রোমে অ্যারে.স্প্লাইস () এর সময় জটিলতা কী?


এই উত্তরটি কীভাবে হয়Is there a good reason to choose [splice into location found] over [push & sort]?
গ্রেইবার্ড

1
@ গ্রেইবার্ড এটি শিরোনামের উত্তর দেয়। দু: খজনকভাবে দুটি পছন্দই দক্ষ নয়।
qwr

কোনও অ্যারে কার্যকর হতে পারে যদি তারা কোনও অ্যারের অনেকগুলি উপাদান অনুলিপি করে।
qwr

1

এখানে আমার ফাংশনটি রয়েছে, আইটেমটি সন্ধান করতে বাইনারি অনুসন্ধান ব্যবহার করে এবং তারপর যথাযথভাবে সন্নিবেশ করান:

function binaryInsert(val, arr){
    let mid, 
    len=arr.length,
    start=0,
    end=len-1;
    while(start <= end){
        mid = Math.floor((end + start)/2);
        if(val <= arr[mid]){
            if(val >= arr[mid-1]){
                arr.splice(mid,0,val);
                break;
            }
            end = mid-1;
        }else{
            if(val <= arr[mid+1]){
                arr.splice(mid+1,0,val);
                break;
            }
            start = mid+1;
        }
    }
    return arr;
}

console.log(binaryInsert(16, [
    5,   6,  14,  19, 23, 44,
   35,  51,  86,  68, 63, 71,
   87, 117
 ]));


0

প্রতিটি আইটেম, তার ওভারকিল পরে পুনরায় বাছাই করবেন না ..

যদি oneোকানোর জন্য কেবল একটি আইটেম থাকে তবে আপনি বাইনারি অনুসন্ধান ব্যবহার করে সন্নিবেশ করার জন্য অবস্থানটি সন্ধান করতে পারেন। তারপরে সন্নিবেশ করা স্থানটির জন্য বাকী আইটেমগুলি অনুলিপি করে মেমকি বা অন্যান্য পরিমাণে অনুরূপ ব্যবহার করুন। বাইনারি অনুসন্ধানটি হ'ল (লগ এন), এবং অনুলিপিটি হ'ল (এন + লগ এন) প্রদান করে ( উপরের পদ্ধতিগুলি ব্যবহার করে, আপনি প্রতিটি সন্নিবেশের পরে পুনরায় বাছাই করছেন যা ও (এন লগ এন)।

এটা কোন ব্যাপার? ধরুন আপনি এলোমেলোভাবে কে উপাদানগুলি সন্নিবেশ করছেন যেখানে k = 1000. সাজানো তালিকাটি 5000 টি আইটেম।

  • Binary search + Move = k*(n + log n) = 1000*(5000 + 12) = 5,000,012 = ~5 million ops
  • Re-sort on each = k*(n log n) = ~60 million ops

যদি itemsোকানোর জন্য আই আইটেমগুলি যখনই আসে, তবে আপনাকে অবশ্যই অনুসন্ধান + সরানো উচিত। তবে, যদি আপনাকে সময়ের আগে - বাছাই করা অ্যারেতে প্রবেশ করার জন্য কে আইটেমের তালিকা দেওয়া হয় তবে আপনি আরও ভাল করতে পারেন। ইতিমধ্যে সাজানো এন অ্যারে থেকে আলাদা করে কে আইটেমগুলি বাছাই করুন। তারপরে একটি স্ক্যান বাছাই করুন, যাতে আপনি উভয় বাছাই করা অ্যারে এক সাথে অন্যটিতে মিশ্রিত করেন down - এক-পদক্ষেপ মার্জ সাজ্ট = কে লগ কে + এন = 9965 + 5000 = ~ 15,000 অপস

আপডেট: আপনার প্রশ্ন সম্পর্কিত।
First method = binary search+move = O(n + log n)Second method = re-sort = O(n log n)আপনি যে সময়টি নিচ্ছেন তা হুবহু ব্যাখ্যা করে।


হ্যাঁ, তবে না এটি আপনার বাছাই করা অ্যালগরিদমের উপর নির্ভর করে। বিপরীত ক্রমে বুদ্বুদ সাজানোর সাহায্যে, আপনার উপাদান বাছাই যদি শেষ উপাদানটি সাজানো না হয় তবে সর্বদা ও (এন) এ থাকে
njzk2

-1
function insertOrdered(array, elem) {
    let _array = array;
    let i = 0;
    while ( i < array.length && array[i] < elem ) {i ++};
    _array.splice(i, 0, elem);
    return _array;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.