दो सॉर्ट किए गए सरणियों को एक क्रमबद्ध सरणी में कैसे मर्ज किया जाए? [बन्द है]


160

यह मुझसे एक साक्षात्कार में पूछा गया था और यह मेरे द्वारा प्रदान किया गया समाधान है:

public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;
    while (i < a.length && j < b.length)
    {
        if (a[i] < b[j])
        {
            answer[k] = a[i];
            i++;
        }
        else
        {
            answer[k] = b[j];
            j++;
        }
        k++;
    }

    while (i < a.length)
    {
        answer[k] = a[i];
        i++;
        k++;
    }

    while (j < b.length)
    {
        answer[k] = b[j];
        j++;
        k++;
    }

    return answer;
}

क्या ऐसा करने का अधिक कुशल तरीका है?

संपादित करें: सही लंबाई के तरीके।


30
मेरे लिए एक बहुत अच्छा जवाब की तरह लग रहा है। इस समस्या में O (n) जटिलता सबसे अच्छी होगी, और आपका जवाब यह प्राप्त करता है। किसी भी चीज की सूक्ष्म रूपीकरण होगा।
ड्रयू हॉल

3
तुमने अच्छा किया! यह अनिवार्य रूप से मर्ज सॉर्ट का एक हिस्सा है: दो सॉर्ट किए गए स्ट्रीम (टेप या डिस्क से) को किसी अन्य सॉर्ट किए गए स्ट्रीम में मर्ज करना।
व्लादिमीर Dyuzhev

9
क्या आपको काम मिल गया है?
शाई

5
इसके अलावा आप टेनेरी ऑपरेटर का उपयोग कर सकते हैं: while (i < a.length && j < b.length) answer[k++] = a[i] < b[j] ? a[i++] : b[j++]; जावा भाषा विनिर्देश: सशर्त ऑपरेटर? :
एंटोन डोजोर्टसेव

1
आप टिप्पणी करना भूल गए !!!
LiziPizi 16

जवाबों:


33

एक मामूली सुधार, लेकिन मुख्य लूप के बाद, आप System.arraycopyइनपुट इनपुट सरणी की पूंछ को कॉपी करने के लिए उपयोग कर सकते हैं जब आप दूसरे के अंत में पहुंचते हैं। O(n)हालांकि, यह आपके समाधान की प्रदर्शन विशेषताओं को नहीं बदलेगा ।


109
public static int[] merge(int[] a, int[] b) {

    int[] answer = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;

    while (i < a.length && j < b.length)  
       answer[k++] = a[i] < b[j] ? a[i++] :  b[j++];

    while (i < a.length)  
        answer[k++] = a[i++];

    while (j < b.length)    
        answer[k++] = b[j++];

    return answer;
}

थोड़ा और अधिक कॉम्पैक्ट है, लेकिन वास्तव में एक ही है!


उस व्यक्ति के लिए जिसने यह कहा कि यह एक सीमा से बाहर का अपवाद है कि आप कौन से इनपुट का उपयोग कर रहे हैं? यह मेरे लिए सभी मामलों में काम करता है।
माइक साउल

1
लूप वेरिएबल और लूप नियंत्रण की घोषणा करने वाली लाइनों को मर्ज करने के लिए लूप के लिए उपयोग करें। समरुपतापूर्वक दोहराई गई खाली लाइनों का उपयोग करें - सममित "पूंछ प्रतियों" के बीच बिना किसी बाधा के दिखता है।
ग्रेबियर

58

मुझे आश्चर्य है कि किसी ने भी इस बारे में अधिक शांत, कुशल और कॉम्पैक्ट कार्यान्वयन का उल्लेख नहीं किया है:

public static int[] merge(int[] a, int[] b) {
    int[] answer = new int[a.length + b.length];
    int i = a.length - 1, j = b.length - 1, k = answer.length;

    while (k > 0)
        answer[--k] =
                (j < 0 || (i >= 0 && a[i] >= b[j])) ? a[i--] : b[j--];
    return answer;
}

रुचियों के बिंदु

  1. ध्यान दें कि यह किसी भी अन्य O (n) एल्गोरिथ्म के समान या कम संख्या में ऑपरेशन करता है लेकिन शाब्दिक रूप से एक ही समय में एक ही लूप में!
  2. यदि दो सरणियाँ लगभग समान आकार की हैं तो O (n) के लिए स्थिर समान है। हालाँकि, अगर सरणियों को वास्तव में असंतुलित किया जाता है, तो संस्करण के साथ System.arraycopyजीत होगी क्योंकि आंतरिक रूप से यह एकल x86 विधानसभा निर्देश के साथ ऐसा कर सकता है।
  3. के a[i] >= b[j]बजाय नोटिस a[i] > b[j]। यह "स्थिरता" की गारंटी देता है जिसे तब परिभाषित किया जाता है जब ए और बी के तत्व समान होते हैं, हम पहले बी से तत्व चाहते हैं।

यह वास्तव में एक अच्छा दृष्टिकोण है। मुझे स्विफ्ट लैंग में अपने मर्ज सॉर्ट एल्गोरिदम पर अच्छे बेंचमार्क प्राप्त करने में परेशानी हुई। इस पर विचार करने से मुझे जो चाहिए था, बहुत बहुत धन्यवाद
चकेले

लूप में (j <0) बिंदु क्या है? Btw, +1, यह वास्तव में अच्छा है! साझा करने के लिए धन्यवाद।
हेंगमेह

2
@Hengameh मामले में j < 0, bपहले से ही समाप्त हो रहा है तो हम शेष जोड़ने रखने aके लिए तत्वों answer सरणी
नतन Streppel

6
मेरे दिमाग में बहुत "चतुर" और पढ़ने के लिए कठिन। मैं विशेष रूप से कोड पढ़ना आसान पसंद करता हूं क्योंकि आप वास्तव में इस कोड के साथ किसी भी प्रदर्शन सुधार को प्राप्त नहीं कर रहे हैं।
केविन एम

1
सूचना के लिए प्लस पॉइंट, और [i]> b [j] के बजाय [i] = b [j]। यह "स्थिरता" की गारंटी देता है
यान खोंस्की

16

जो भी सुधार किए जा सकते हैं वे सूक्ष्म-अनुकूलन होंगे, समग्र एल्गोरिथ्म सही है।


यदि a बड़ा है और b छोटा है तो यह एल्गोरिथ्म गलत है।
जैक

7
यह गलत नहीं है लेकिन कुशल नहीं है।
जैक

@ जक आप इसे O (n) से अधिक तेज कैसे कर सकते हैं जब आप n वस्तुओं की एक सरणी का निर्माण कर रहे हैं?
विल

@w बेवकूफ़ी System.arrayCopy()से तेज़ है क्योंकि यह सीपीयू-अनुकूलित memcpyकॉल का उपयोग करता है । तो वहाँ विखंडू की नकल करके प्रदर्शन में सुधार करने की गुंजाइश है। सीमाओं के लिए द्विआधारी खोज की भी गुंजाइश है।
स्लिम

खासकर यदि आप सॉर्ट किए गए प्रकृति का उपयोग कर सकते हैं तो अधिकांश प्रविष्टियों को छोड़ दें और उनकी तुलना कभी न करें। आप वास्तव में O (n) को हरा सकते हैं।
ताताराइज़ करें

10

यह समाधान भी अन्य पदों के समान है सिवाय इसके कि यह शेष सरणी तत्वों को कॉपी करने के लिए System.arrayCopy का उपयोग करता है।

private static int[] sortedArrayMerge(int a[], int b[]) {
    int result[] = new int[a.length +b.length];
    int i =0; int j = 0;int k = 0;
    while(i<a.length && j <b.length) {
        if(a[i]<b[j]) {
            result[k++] = a[i];
            i++;
        } else {
            result[k++] = b[j];
            j++;
        }
    }
    System.arraycopy(a, i, result, k, (a.length -i));
    System.arraycopy(b, j, result, k, (b.length -j));
    return result;
}

7

यहाँ अद्यतन कार्य है। यह डुप्लिकेट को हटाता है, उम्मीद है कि किसी को यह प्रयोग करने योग्य मिलेगा:

public static long[] merge2SortedAndRemoveDublicates(long[] a, long[] b) {
    long[] answer = new long[a.length + b.length];
    int i = 0, j = 0, k = 0;
    long tmp;
    while (i < a.length && j < b.length) {
        tmp = a[i] < b[j] ? a[i++] : b[j++];
        for ( ; i < a.length && a[i] == tmp; i++);
        for ( ; j < b.length && b[j] == tmp; j++);
        answer[k++] = tmp;
    }
    while (i < a.length) {
        tmp = a[i++];
        for ( ; i < a.length && a[i] == tmp; i++);
        answer[k++] = tmp;
    }
    while (j < b.length) {
        tmp = b[j++];
        for ( ; j < b.length && b[j] == tmp; j++);
        answer[k++] = tmp;
    }
    return Arrays.copyOf(answer, k);
}

+1, साझा करने के लिए धन्यवाद। एक प्रश्न: आपने अरेंज्ड टाइप और वेरिएबल 'टेम्प' के प्रकार को लंबे समय तक क्यों चुना?
हेंगामेह

(मुझे विधि के नाम के बारे में संदेह है।)
ग्रेबियर

5

इसे नीचे दिए गए 4 कथनों में किया जा सकता है

 int a[] = {10, 20, 30};
 int b[]= {9, 14, 11};
 int res[]=new int[a.legth+b.length]; 
 System.arraycopy(a,0, res, 0, a.length); 
 System.arraycopy(b,0,res,a.length, b.length);
 Array.sort(res)


5
मुझे समझ नहीं आता कि इस जवाब को नकारात्मक वोट क्यों मिले। यह सच है कि यह कुशल नहीं है। लेकिन कभी-कभी आप सभी को काम जल्द से जल्द पूरा करना होता है। यदि आप बहुत छोटे सरणियों के साथ काम कर रहे हैं, तो 100 से कम तत्वों को कहें, मैं एक लंबा कोड लिखने के बजाय उपरोक्त कोड का उपयोग करना पसंद करूंगा जो किसी भी महत्वपूर्ण प्रदर्शन में सुधार नहीं करेगा। तो, सुधीर को यह आसान समाधान प्रदान करने के लिए धन्यवाद और इसे संपादित करने के लिए SANN3।
अहमदोव

2
अलिखित आधार यह है कि कोई sortफ़ंक्शन स्वयं को सॉर्ट करने की विधि के रूप में उपयोग नहीं कर सकता है। यह पुनरावृत्ति के बजाय अनंत प्रतिगमन होगा। इसके अलावा दूसरा आधार यह है कि merge_array वह फ़ंक्शन है जो क्रॉप करता है। इस प्रकार यह उत्तर सबसे अधिक संभावित संदर्भ में अनुपयोगी है।
अकी सुहिचोनें

पूछे गए प्रश्न में उल्लेख नहीं है कि आवश्यक कोड केवल छोटे सरणी के लिए था। इसलिए यह उत्तर भ्रामक होगा जब तक कि यह स्पष्ट रूप से इसकी सीमा नहीं बताता। नीचे मेरा जवाब भी देखिए। कुशल कोड लिखने के लिए समान संख्या में लाइनें लगती हैं जो किसी भी सरणी आकार के लिए काम करती है :)
शीतल शाह

प्रश्न ने निर्धारित किया कि सरणियाँ पहले से ही क्रमबद्ध हैं। यदि सरणियाँ बहुत बड़ी हो सकती हैं, तो यह समाधान रुक जाएगा और खराब प्रदर्शन करेगा। इसलिए सुनिश्चित करें कि आपको आवश्यक अंतिम परिणाम मिलेंगे, लेकिन ऐप प्रदर्शन नहीं करेगा और यदि मैं साक्षात्कार दे रहा था तो आपको नौकरी नहीं मिलेगी।
केविन एम

Array.sort () फ़ंक्शन TimSort का उपयोग करता है जो बहुत अधिक सॉर्ट किए गए रन ढूंढेगा और उन पर एक मर्ज सॉर्ट लागू करेगा। विचित्र रूप से पर्याप्त है, यह कोड वास्तव में "कुशल नहीं" के लिए भी दोषपूर्ण हो सकता है यह वास्तव में सॉर्ट किए गए रनों के कारण ओ (एन) समय में परिष्करण में गिर जाएगा। आप इस पर बेंचमार्क का एक गुच्छा चला सकते हैं, यह अच्छा है कि यह ओपी कोड को काफी बार हरा देगा।
ताताराइज करें

4

मुझे इसे जावास्क्रिप्ट में लिखना था, यहाँ यह है:

function merge(a, b) {
    var result = [];
    var ai = 0;
    var bi = 0;
    while (true) {
        if ( ai < a.length && bi < b.length) {
            if (a[ai] < b[bi]) {
                result.push(a[ai]);
                ai++;
            } else if (a[ai] > b[bi]) {
                result.push(b[bi]);
                bi++;
            } else {
                result.push(a[ai]);
                result.push(b[bi]);
                ai++;
                bi++;
            }
        } else if (ai < a.length) {
            result.push.apply(result, a.slice(ai, a.length));
            break;
        } else if (bi < b.length) {
            result.push.apply(result, b.slice(bi, b.length));
            break;
        } else {
            break;
        }
    }
    return result;
}

4

अपाचे संग्रह संस्करण 4 के बाद से कोलाट विधि का समर्थन करता है; आप इस collateविधि का उपयोग करके ऐसा कर सकते हैं :

org.apache.commons.collections4.CollectionUtils

यहाँ javadoc से बोली:

collate(Iterable<? extends O> a, Iterable<? extends O> b, Comparator<? super O> c)

दो सॉर्ट किए गए संग्रह को जोड़ता है, aऔर b, एक एकल, सॉर्ट की गई सूची में ऐसा होता है कि तुलनात्मक सी के अनुसार तत्वों का क्रम बनाए रखा जाता है।

पहिया का फिर से आविष्कार न करें! दस्तावेज़ संदर्भ: http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html


4

GallopSearch मर्ज: O (n) * log (i) (O ) बजाय O (n)

मैंने आगे बढ़कर टिप्पणियों में ग्रेबर्ड सुझाव लागू किया। ज्यादातर क्योंकि मुझे इस कोड के एक अत्यधिक कुशल मिशन महत्वपूर्ण संस्करण की आवश्यकता थी।

  • कोड एक सरपट खोज का उपयोग करता है जो ओ (लॉग (आई)) है जहां मैं वर्तमान सूचकांक से दूरी प्रासंगिक सूचकांक मौजूद है।
  • सरपट खोज के बाद उचित, श्रेणी की पहचान के लिए कोड एक बाइनरीसर्च का उपयोग करता है। चूंकि सरपट इसे एक छोटी सीमा तक सीमित करता है जिसके परिणामस्वरूप बाइनरीसर्च भी हे (लॉग (आई))
  • सरपट और मर्ज पीछे की ओर किए जाते हैं। यह मिशन महत्वपूर्ण नहीं लगता, लेकिन यह एरेज़ के विलय के स्थान पर अनुमति देता है। यदि आपके सरणियों में से एक में परिणाम मानों को संग्रहीत करने के लिए पर्याप्त जगह है, तो आप बस इसे विलय सरणी और परिणाम सरणी के रूप में उपयोग कर सकते हैं । आपको ऐसे मामले में सरणी के भीतर मान्य श्रेणी निर्दिष्ट करनी होगी।
  • इसके लिए उस मामले में मेमोरी आवंटन की आवश्यकता नहीं है (महत्वपूर्ण कार्यों में बड़ी बचत)। यह केवल यह सुनिश्चित करता है कि यह किसी भी असंसाधित मूल्यों को अधिलेखित नहीं करता है (जो केवल पीछे की ओर किया जा सकता है)। वास्तव में, आप इनपुट और परिणाम दोनों के लिए एक ही सरणी का उपयोग करते हैं। इसका कोई बुरा प्रभाव नहीं पड़ेगा।
  • मैंने लगातार Integer.compare () का उपयोग किया ताकि इसे अन्य उद्देश्यों के लिए स्विच किया जा सके।
  • वहाँ कुछ मौका है कि मैं एक छोटे से नासमझ है और मैं पहले से साबित कर दिया है जानकारी का उपयोग नहीं किया जा सकता है। जैसे कि द्विआधारी दो मानों की श्रेणी में खोज, जिसके लिए पहले से ही एक मूल्य की जाँच की गई थी। मुख्य लूप को निर्दिष्ट करने का एक बेहतर तरीका भी हो सकता है, फ़्लिपिंग सी मूल्य की आवश्यकता नहीं होगी यदि उन्हें अनुक्रम में दो संचालन में जोड़ा गया। चूँकि आप जानते हैं कि आप एक करेंगे तो दूसरा हर। कुछ पॉलिश के लिए जगह है।

ऐसा करने के लिए यह सबसे कुशल तरीका होना चाहिए, ओ (एन) के बजाय ओ (लॉग (एन) * लॉग (आई) की समय जटिलता के साथ । और ओ (एन) की सबसे खराब स्थिति समय की जटिलता। यदि आपके सरणियाँ अव्यवस्थित हैं और एक साथ मूल्यों के लंबे तार हैं, तो यह इसे करने के लिए किसी अन्य तरीके को बौना कर देगा, अन्यथा यह सिर्फ उनसे बेहतर होगा।

यह मर्ज सरणी के सिरों पर दो रीड वैल्यू और परिणाम एरे के भीतर राइट वैल्यू है। यह पता लगाने के बाद कि कौन सा अंतिम मूल्य कम है, यह उस सरणी में सरपट खोज करता है। १, २, ४,,, १६, ३२, इत्यादि। जब यह वह सीमा पाता है जहाँ दूसरे सरणी का वाच मान बड़ा होता है। यह बाइनरी उस सीमा में खोज करता है (आधे में सीमा को काटता है, सही आधा खोजता है, एकल मूल्य तक दोहराता है)। फिर यह सरणी उन मानों को लिखने की स्थिति में कॉपी करता है। इस बात को ध्यान में रखते हुए कि प्रतिलिपि आवश्यकता के आधार पर ऐसी है कि यह या तो पढ़ने वाले सरणी से समान मानों को अधिलेखित नहीं कर सकती है (जिसका अर्थ है कि लेखन सरणी और रीड सरणी समान हो सकती है)। यह तब दूसरे सरणी के लिए एक ही ऑपरेशन करता है जिसे अब अन्य सरणी के नए रीड वैल्यू से कम जाना जाता है।

static public int gallopSearch(int current, int[] array, int v) {
    int d = 1;
    int seek = current - d;
    int prevIteration = seek;
    while (seek > 0) {
        if (Integer.compare(array[seek], v) <= 0) {
            break;
        }
        prevIteration = seek;
        d <<= 1;
        seek = current - d;
        if (seek < 0) {
            seek = 0;
        }
    }
    if (prevIteration != seek) {
        seek = binarySearch(array, seek, prevIteration, v);
        seek = seek >= 0 ? seek : ~seek;
    }
    return seek;
}

static public int binarySearch(int[] list, int fromIndex, int toIndex, int v) {
    int low = fromIndex;
    int high = toIndex - 1;
    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = list[mid];
        int cmp = Integer.compare(midVal, v);
        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            return mid;// key found
        }
    }
    return -(low + 1);// key not found.
}

static public int[] sortedArrayMerge(int[] a, int[] b) {
    return sortedArrayMerge(null, a, a.length, b, b.length);
}

static public int[] sortedArrayMerge(int[] results, int[] a, int aRead, int b[], int bRead) {
    int write = aRead + bRead, length, gallopPos;
    if ((results == null) || (results.length < write)) {
        results = new int[write];
    }
    if (aRead > 0 && bRead > 0) {
        int c = Integer.compare(a[aRead - 1], b[bRead - 1]);
        while (aRead > 0 && bRead > 0) {
            switch (c) {
                default:
                    gallopPos = gallopSearch(aRead, a, b[bRead-1]);
                    length = (aRead - gallopPos);
                    write -= length;
                    aRead = gallopPos;
                    System.arraycopy(a, gallopPos--, results, write, length);
                    c = -1;
                    break;
                case -1:
                    gallopPos = gallopSearch(bRead, b, a[aRead-1]);
                    length = (bRead - gallopPos);
                    write -= length;
                    bRead = gallopPos;
                    System.arraycopy(b, gallopPos--, results, write, length);
                    c = 1;
                    break;
            }
        }
    }
    if (bRead > 0) {
        if (b != results) {
            System.arraycopy(b, 0, results, 0, bRead);
        }
    } else if (aRead > 0) {
        if (a != results) {
            System.arraycopy(a, 0, results, 0, aRead);
        }
    }
    return results;
}

यह इसे करने का सबसे कुशल तरीका होना चाहिए।


कुछ उत्तरों में डुप्लिकेट हटाने की क्षमता थी। आपको एक O (n) एल्गोरिथ्म की आवश्यकता होगी क्योंकि आपको वास्तव में प्रत्येक आइटम की तुलना करनी चाहिए। इस तथ्य के बाद लागू होने के लिए यहां एक स्टैंड-अलोन है। यदि आप उन सभी को देखने की जरूरत है, तो आप कई प्रविष्टियों के माध्यम से सभी तरीकों से सरपट नहीं कर सकते हैं, हालांकि आप डुप्लिकेट के माध्यम से सरपट कर सकते हैं, अगर आपके पास उनमें से बहुत कुछ था।

static public int removeDuplicates(int[] list, int size) {
    int write = 1;
    for (int read = 1; read < size; read++) {
        if (list[read] == list[read - 1]) {
            continue;
        }
        list[write++] = list[read];
    }
    return write;
}

अद्यतन: पिछला उत्तर, भयानक कोड नहीं, लेकिन स्पष्ट रूप से ऊपर से नीच।

एक और अनावश्यक हाइपर-ऑप्टिमाइज़ेशन। यह न केवल अंत बिट्स के लिए एरेस्कोपी को आमंत्रित करता है, बल्कि शुरुआत के लिए भी। डेटा में एक बाइनरीसर्च द्वारा ओ (लॉग (एन)) में किसी भी परिचयात्मक गैर-ओवरलैप को संसाधित करना। O (लॉग (n) + n) O (n) है और कुछ मामलों में प्रभाव विशेष रूप से उन चीजों का स्पष्ट रूप से उच्चारण किया जाएगा, जहां विलय ऐरे के बीच कोई ओवरलैप नहीं है।

private static int binarySearch(int[] array, int low, int high, int v) {
    high = high - 1;
    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = array[mid];
        if (midVal > v)
            low = mid + 1;
        else if (midVal < v)
            high = mid - 1;
        else
            return mid; // key found
    }
    return low;//traditionally, -(low + 1);  // key not found.
}

private static int[] sortedArrayMerge(int a[], int b[]) {
    int result[] = new int[a.length + b.length];
    int k, i = 0, j = 0;
    if (a[0] > b[0]) {
        k = i = binarySearch(b, 0, b.length, a[0]);
        System.arraycopy(b, 0, result, 0, i);
    } else {
        k = j = binarySearch(a, 0, a.length, b[0]);
        System.arraycopy(a, 0, result, 0, j);
    }
    while (i < a.length && j < b.length) {
        result[k++] = (a[i] < b[j]) ? a[i++] : b[j++];
    }
    if (j < b.length) {
        System.arraycopy(b, j, result, k, (b.length - j));
    } else {
        System.arraycopy(a, i, result, k, (a.length - i));
    }
    return result;
}

1
समरूपता के बारे में कुछ करने के लिए शुरू करने के लिए अपवित्र, लेकिन वहां क्यों रुकें? सरपट खोज का उपयोग करें, क्या यह बराबर कुंजियों के बाद सूचकांक लौटाता है । सरणी कॉपी का उपयोग करें यदि 3 से अधिक तत्व हैं, केवल। ध्यान दें कि उस प्रतिलिपि के बाद, कुछ भी नहीं बदला (क) एक इनपुट में प्रारंभिक सूचकांक और आउटपुट सरणी b) आपका ज्ञान जिसके बारे में "अगला" तत्व छोटा है।
ग्रेबियर

यह पूरी तरह से कार्यान्वित Arrays.sort करता है। यह उल्लेखनीय रूप से एक मर्ज प्रकार है। मुझे लगता है कि वे 2 तत्वों की अदला-बदली करते हैं जहाँ ज़रूरत होती है लेकिन 2 से अधिक तत्वों के लिए एरेस्कोपी में आते हैं। मैं इस बारे में अनिश्चित हूं कि क्या आप अगले तत्व को रैखिक रूप से जांचेंगे या बाइनरी सर्च करेंगे। अगर आप उस दूरी को सरपट कर सकते हैं तो बड़ी दूरी तक सट्टा चेक करने के लिए एक बहुत बड़ा फायदा होगा। जैसे कि आगे 8 चेक करें, और यदि आप कॉपी कर सकते हैं कि आपने खुद को उन चीजों के 7 संचालन को बचाया है जिन्हें आपको देखने की आवश्यकता नहीं है।
तातार

@greybeard ... और किया। इसके अलावा पीछे की ओर गया ताकि मैं उसी मेमोरी का पुन: उपयोग कर सकूं।
तातार

अच्छी बात है कि आपने बैलिस्टिक जाने के लिए प्रेरित किया। दिन के समय डूबने के बाद करीब से जाना।
ग्रेबियर

That is totally what the implemented Arrays.sort does( यह कि आपके उत्तर के पहले संशोधन से - या - मेरी 19 फरवरी की टिप्पणी से?) - सनसॉफ्ट की JDK 8 में भी नहीं मिल सकता है: आप किस कार्यान्वयन की Arrays.sortबात कर रहे हैं?
ग्रेबियर

2

यहाँ जावास्क्रिप्ट में एक छोटा रूप लिखा गया है:

function sort( a1, a2 ) {

    var i = 0
        , j = 0
        , l1 = a1.length
        , l2 = a2.length
        , a = [];

    while( i < l1 && j < l2 ) {

        a1[i] < a2[j] ? (a.push(a1[i]), i++) : (a.push( a2[j]), j++);
    }

    i < l1 && ( a = a.concat( a1.splice(i) ));
    j < l2 && ( a = a.concat( a2.splice(j) ));

    return a;
}

1
    public class Merge {

    // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
    public static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {

        // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
        assert isSorted(a, lo, mid);
        assert isSorted(a, mid+1, hi);

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k]; 
        }

        // merge back to a[]
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)              a[k] = aux[j++];
            else if (j > hi)               a[k] = aux[i++];
            else if (less(aux[j], aux[i])) a[k] = aux[j++];
            else                           a[k] = aux[i++];
        }

        // postcondition: a[lo .. hi] is sorted
        assert isSorted(a, lo, hi);
    }

    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, aux, lo, mid);
        sort(a, aux, mid + 1, hi);
        merge(a, aux, lo, mid, hi);
    }

    public static void sort(Comparable[] a) {
        Comparable[] aux = new Comparable[a.length];
        sort(a, aux, 0, a.length-1);
        assert isSorted(a);
    }


   /***********************************************************************
    *  Helper sorting functions
    ***********************************************************************/

    // is v < w ?
    private static boolean less(Comparable v, Comparable w) {
        return (v.compareTo(w) < 0);
    }

    // exchange a[i] and a[j]
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }


   /***********************************************************************
    *  Check if array is sorted - useful for debugging
    ***********************************************************************/
    private static boolean isSorted(Comparable[] a) {
        return isSorted(a, 0, a.length - 1);
    }

    private static boolean isSorted(Comparable[] a, int lo, int hi) {
        for (int i = lo + 1; i <= hi; i++)
            if (less(a[i], a[i-1])) return false;
        return true;
    }


   /***********************************************************************
    *  Index mergesort
    ***********************************************************************/
    // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
    private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) {

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = index[k]; 
        }

        // merge back to a[]
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)                    index[k] = aux[j++];
            else if (j > hi)                     index[k] = aux[i++];
            else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++];
            else                                 index[k] = aux[i++];
        }
    }

    // return a permutation that gives the elements in a[] in ascending order
    // do not change the original array a[]
    public static int[] indexSort(Comparable[] a) {
        int N = a.length;
        int[] index = new int[N];
        for (int i = 0; i < N; i++)
            index[i] = i;

        int[] aux = new int[N];
        sort(a, index, aux, 0, N-1);
        return index;
    }

    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
    private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, index, aux, lo, mid);
        sort(a, index, aux, mid + 1, hi);
        merge(a, index, aux, lo, mid, hi);
    }

    // print array to standard output
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            StdOut.println(a[i]);
        }
    }

    // Read strings from standard input, sort them, and print.
    public static void main(String[] args) {
        String[] a = StdIn.readStrings();
        Merge.sort(a);
        show(a);
    }
}

इस प्रति a[mid+1 .. hi]के auxलिए क्या करता है ?
ग्रेबियर

1

मुझे लगता है कि बड़े सॉर्ट किए गए एरे के लिए स्किप लिस्ट शुरू करने से तुलना की संख्या कम हो सकती है और तीसरे एरे में कॉपी करने की प्रक्रिया में तेजी आ सकती है। यह बहुत अच्छा हो सकता है यदि सरणी बहुत बड़ा है।


1
public int[] merge(int[] a, int[] b) {
    int[] result = new int[a.length + b.length];
    int aIndex, bIndex = 0;

    for (int i = 0; i < result.length; i++) {
        if (aIndex < a.length && bIndex < b.length) {
            if (a[aIndex] < b[bIndex]) {
                result[i] = a[aIndex];
                aIndex++;
            } else {
                result[i] = b[bIndex];
                bIndex++;
            }
        } else if (aIndex < a.length) {
            result[i] = a[aIndex];
            aIndex++;
        } else {
            result[i] = b[bIndex];
            bIndex++;
        }
    }

    return result;
}

2
कुछ स्पष्टीकरण अच्छा होगा। :)
gsamaras

1
public static int[] merge(int[] a, int[] b) {
    int[] mergedArray = new int[(a.length + b.length)];
    int i = 0, j = 0;
    int mergedArrayIndex = 0;
    for (; i < a.length || j < b.length;) {
        if (i < a.length && j < b.length) {
            if (a[i] < b[j]) {
                mergedArray[mergedArrayIndex] = a[i];
                i++;
            } else {
                mergedArray[mergedArrayIndex] = b[j];
                j++;
            }
        } else if (i < a.length) {
            mergedArray[mergedArrayIndex] = a[i];
            i++;
        } else if (j < b.length) {
            mergedArray[mergedArrayIndex] = b[j];
            j++;
        }
        mergedArrayIndex++;
    }
    return mergedArray;
}

इसको बचाने की कृपा क्या है? यह सिकुड़ सकता है for (int i, j, k = i = j = 0 ; k < c.length ; ) c[k++] = b.length <= j || i < a.length && a[i] < b[j] ? a[i++] : b[j++];। यह एंड्रयू के 2014 के उत्तर से कैसे भिन्न है ?
ग्रेबियर

1

एल्गोरिथम को कई तरीकों से बढ़ाया जा सकता है। उदाहरण के लिए, यह जाँच करना उचित है, यदि a[m-1]<b[0]या b[n-1]<a[0]। उन मामलों में से किसी में, अधिक तुलना करने की आवश्यकता नहीं है। एल्गोरिथ्म सिर्फ सही क्रम में एक परिणाम में स्रोत सरणियों की प्रतिलिपि बना सकता है।

अधिक जटिल संवर्द्धन में इंटरलेविंग पार्ट्स की खोज करना और केवल उनके लिए मर्ज अल्गोरिद्म चलाना शामिल हो सकता है। यह बहुत समय बचा सकता है, जब मर्ज किए गए सरणियों के आकार समय के स्कोर में भिन्न होते हैं।


इस वृद्धि के लिए यह जांचना बेहतर होगा कि पहला तत्व द्विआधारी खोज के साथ दूसरे सरणी में कहां गिरता है, फिर उस डेटा को शुरू करने के लिए सरणी। फिर इस मामले में कि उन जाँचों में से एक सच है, यह बस सब कुछ सरणी और फिर ternary सरणी और आप एक ही परिणाम प्राप्त होगा। लेकिन, ओवरलैप के एक छोटे से मामले में, आपको केवल ओवरलैप के दौरान उचित एल्गोरिथ्म करने की आवश्यकता है और कोई अन्य समय नहीं। चूँकि आप कुछ जल्दी ओ (logn) कमांड का उपयोग करते हुए O (n) के साथ फंस गए हैं, इससे पहले कुछ भी खर्च नहीं होने वाला है।
ताताराइज करें

1

यह समस्या मर्जर्स एल्गोरिथ्म से संबंधित है, जिसमें दो सॉर्ट किए गए उप-सरणियों को एक एकल सॉर्ट किए गए उप-सरणी में जोड़ा जाता है। CLRS पुस्तक एल्गोरिथ्म का एक उदाहरण देता है और पता चल सके कि अंत में एक प्रहरी मूल्य (कुछ है कि तुलना करता है और "किसी भी अन्य मूल्य से अधिक") प्रत्येक सरणी के अंत में जोड़कर तक पहुँच गया है के लिए की जरूरत को साफ।

मैंने इसे पायथन में लिखा था, लेकिन इसे जावा में भी अच्छी तरह से अनुवाद करना चाहिए:

def func(a, b):
    class sentinel(object):
        def __lt__(*_):
            return False

    ax, bx, c = a[:] + [sentinel()], b[:] + [sentinel()], []
    i, j = 0, 0

    for k in range(len(a) + len(b)):
        if ax[i] < bx[j]:
            c.append(ax[i])
            i += 1
        else:
            c.append(bx[j])
            j += 1

    return c

थोक तत्वों को एक बार (स्किल्ली) से एक सेंटिनल का उपयोग करते हुए कॉपी करें ...
greybeard

1

आप परिणामी सरणी को भरने के लिए 2 थ्रेड्स का उपयोग कर सकते हैं, एक सामने से, एक पीछे से।

यह संख्या के मामले में किसी भी तुल्यकालन के बिना काम कर सकता है, उदाहरण के लिए यदि प्रत्येक थ्रेड मानों का आधा भाग सम्मिलित करता है।


0
//How to merge two sorted arrays into a sorted array without duplicates?
//simple C Coding
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main()
{
    int InputArray1[] ={1,4,5,7,8,9,12,13,14,17,40};
    int InputArray2[] ={4,5,11,14,15,17,18,19,112,122,122,122,122};
    int n=10;
    int OutputArray[30];
    int i=0,j=0,k=0;
    //k=OutputArray
    while(i<11 && j<13)
    {
        if(InputArray1[i]<InputArray2[j])
        {
            if (k == 0 || InputArray1[i]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray1[i];
            }
            i=i+1;
        }
        else if(InputArray1[i]>InputArray2[j])
        {
            if (k == 0 || InputArray2[j]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray2[j];
            }
            j=j+1;
        }
        else
        {
            if (k == 0 || InputArray1[i]!= OutputArray[k-1])
            {
                OutputArray[k++] = InputArray1[i];
            }
            i=i+1;
            j=j+1;
        }
    };
    while(i<11)
    {
        if(InputArray1[i]!= OutputArray[k-1])
            OutputArray[k++] = InputArray1[i++];
        else
            i++;
    }
    while(j<13)
    {
        if(InputArray2[j]!= OutputArray[k-1])
            OutputArray[k++] = InputArray2[j++];
        else
            j++;
    }
    for(i=0; i<k; i++)
    {
        printf("sorted data:%d\n",OutputArray[i]);
    };
}

0
public static int[] merge(int[] listA, int[] listB) {
        int[] mergedList = new int[ listA.length + listB.length];
        int i = 0; // Counter for listA
        int j = 0; // Counter for listB
        int k = 0; // Counter for mergedList
        while (true) {
            if (i >= listA.length && j >= listB.length) {
                break;
            }
            if (i < listA.length && j < listB.length) { // If both counters are valid.
                if (listA[i] <= listB[j]) {
                    mergedList[k] = listA[i];
                    k++;
                    i++;
                } else {
                    mergedList[k] = listB[j];
                    k++;
                    j++;
                }
            } else if (i < listA.length && j >= listB.length) { // If only A's counter is valid.
                mergedList[k] = listA[i];
                k++;
                i++;
            } else if (i <= listA.length && j < listB.length) { // If only B's counter is valid
                mergedList[k] = listB[j];
                k++;
                j++;
            }
        }
        return mergedList;
    }

0
var arrCombo = function(arr1, arr2){
  return arr1.concat(arr2).sort(function(x, y) {
    return x - y;
  });
};

2
यह उत्तर जावा प्रोग्रामिंग भाषा पर लागू नहीं होता है, हालांकि यह जावास्क्रिप्ट के लिए एक अच्छा जवाब होगा।
gknicker

यह एक नौकरी का साक्षात्कार था। इन मामलों में, आपको ऊपर दिए गए "सामान्य" कोड लिखने की उम्मीद नहीं है। वे "कुशल" कोड और एक प्रदर्शन की तलाश कर रहे हैं जिसे आप शामिल एल्गोरिदम को समझते हैं।
d11wtq

0

मेरी पसंदीदा प्रोग्रामिंग भाषा जावास्क्रिप्ट है

function mergeSortedArrays(a, b){
    var result = [];

    var sI = 0;
    var lI = 0;
    var smallArr;
    var largeArr;
    var temp;

    if(typeof b[0] === 'undefined' || a[0]<b[0]){
        smallArr = a;
        largeArr = b;
    } else{
        smallArr = b;
        largeArr = a;
    }

    while(typeof smallArr[sI] !== 'undefined'){
        result.push(smallArr[sI]);
        sI++;

        if(smallArr[sI]>largeArr[lI] || typeof smallArr[sI] === 'undefined'){
            temp = smallArr;
            smallArr = largeArr;
            largeArr = temp;
            temp = sI;
            sI = lI;
            lI = temp;
        }
    }
    return result;
}

0

शायद System.arraycopy का उपयोग करें

public static byte[] merge(byte[] first, byte[] second){
    int len = first.length + second.length;
    byte[] full = new byte[len];
    System.arraycopy(first, 0, full, 0, first.length);
    System.arraycopy(second, 0, full, first.length, second.length);
    return full;
}

3
तुम सिर्फ उनका विलय कर रहे हो; आपका परिणामी सरणी स्वयं ही क्रमबद्ध नहीं है जो एक आवश्यकता थी।
संजीव धीमान

0
public static void main(String[] args) {
    int[] arr1 = {2,4,6,8,10,999};
    int[] arr2 = {1,3,5,9,100,1001};

    int[] arr3 = new int[arr1.length + arr2.length];

    int temp = 0;

    for (int i = 0; i < (arr3.length); i++) {
        if(temp == arr2.length){
            arr3[i] = arr1[i-temp];
        }
        else if (((i-temp)<(arr1.length)) && (arr1[i-temp] < arr2[temp])){
                arr3[i] = arr1[i-temp];
        }
        else{
            arr3[i] = arr2[temp];
            temp++;
        }
    }

    for (int i : arr3) {
        System.out.print(i + ", ");
    }
}

आउटपुट है:

1, 2, 3, 4, 5, 6, 8, 9, 10, 100, 999, 1001,


सूचकांक में नामकरण के लिए भ्रमित करना , लेकिन arr2नहीं । ind2temp
ग्रेबियर

0

आप कोड को थोड़ा और अधिक कॉम्पैक्ट बनाने के लिए टर्नरी ऑपरेटरों का उपयोग कर सकते हैं

public static int[] mergeArrays(int[] a1, int[] a2) {
    int[] res = new int[a1.length + a2.length];
    int i = 0, j = 0;

    while (i < a1.length && j < a2.length) {
        res[i + j] = a1[i] < a2[j] ? a1[i++] : a2[j++];
    }

    while (i < a1.length) {
        res[i + j] = a1[i++];
    }

    while (j < a2.length) {
        res[i + j] = a2[j++];
    }

    return res;
}

0
public static int[] mergeSorted(int[] left, int[] right) {
    System.out.println("merging " + Arrays.toString(left) + " and " + Arrays.toString(right));
    int[] merged = new int[left.length + right.length];
    int nextIndexLeft = 0;
    int nextIndexRight = 0;
    for (int i = 0; i < merged.length; i++) {
        if (nextIndexLeft >= left.length) {
            System.arraycopy(right, nextIndexRight, merged, i, right.length - nextIndexRight);
            break;
        }
        if (nextIndexRight >= right.length) {
            System.arraycopy(left, nextIndexLeft, merged, i, left.length - nextIndexLeft);
            break;
        }
        if (left[nextIndexLeft] <= right[nextIndexRight]) {
            merged[i] = left[nextIndexLeft];
            nextIndexLeft++;
            continue;
        }
        if (left[nextIndexLeft] > right[nextIndexRight]) {
            merged[i] = right[nextIndexRight];
            nextIndexRight++;
            continue;
        }
    }
    System.out.println("merged : " + Arrays.toString(merged));
    return merged;
}

मूल समाधान से बस एक छोटा सा अलग


0

O (m + n) समय जटिलता में दो सॉर्ट किए गए सरणी को जोड़ने के लिए केवल एक लूप के साथ दृष्टिकोण के नीचे जटिलता का उपयोग करें। m और n पहले एरे और दूसरे एरे की लंबाई है।

public class MargeSortedArray {
    public static void main(String[] args) {
        int[] array = new int[]{1,3,4,7};
        int[] array2 = new int[]{2,5,6,8,12,45};
        int[] newarry = margeToSortedArray(array, array2);
        //newarray is marged array
    }

    // marge two sorted array with o(a+n) time complexity
    public static int[] margeToSortedArray(int[] array, int[] array2) {
        int newarrlen = array.length+array2.length;
        int[] newarr = new int[newarrlen];

        int pos1=0,pos2=0;
        int len1=array.length, len2=array2.length;

        for(int i =0;i<newarrlen;i++) {     
            if(pos1>=len1) {
                newarr[i]=array2[pos2];
                pos2++;
                continue;
            }
            if(pos2>=len2) {
                newarr[i]=array[pos1];
                pos1++;
                continue;
            }

            if(array[pos1]>array2[pos2]) {
                newarr[i]=array2[pos2];
                pos2++;
            } else {
                newarr[i]=array[pos1];
                pos1++;
            }   
        }

        return newarr;
    }

}

0
var arr1 = [2,10,20,30,100];
var arr2 = [2,4,5,6,7,8,9];
var j = 0;
var i =0;
var newArray = [];

for(var x=0;x< (arr1.length + arr2.length);x++){
    if(arr1[i] >= arr2[j]){                //check if element arr2 is equal and less than arr1 element
        newArray.push(arr2[j]);
      j++;
    }else if(arr1[i] < arr2[j]){            //check if element arr1 index value  is less than arr2 element
        newArray.push(arr1[i]);
        i++;
    }
    else if(i == arr1.length || j < arr2.length){    // add remaining arr2 element
        newArray.push(arr2[j]);
        j++
    }else{                                                   // add remaining arr1 element
        newArray.push(arr1[i]); 
        i++
    }

}

console.log(newArray);

-1

चूंकि प्रश्न किसी विशिष्ट भाषा को नहीं मानता है। यहाँ पायथन में समाधान है। मान लें कि सरणियाँ पहले से ही सॉर्ट की गई हैं।

दृष्टिकोण 1 - सुन्न सरणियों का उपयोग करना: सुन्न आयात करना

arr1 = numpy.asarray([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 11, 14, 15, 55])
arr2 = numpy.asarray([11, 32, 43, 45, 66, 76, 88])

array = numpy.concatenate((arr1,arr2), axis=0)
array.sort()

दृष्टिकोण 2 - सूची का उपयोग करना, मान लेना सूचियों को क्रमबद्ध किया जाता है।

list_new = list1.extend(list2)
list_new.sort()

Since the question doesn't assume any specific language2011/5/11/19: 43 से, इसे जावा टैग किया गया है ।
ग्रेबियर

अपने समाधान तथ्य सूचियों का लाभ नहीं ले करता है पहले से ही हल कर रहे हैं, और इसके क्रम नहीं हे (एन) है, के बाद से .sort()है O(n log n)सबसे अच्छे रूप में
dark_ruby

-1

यहाँ मेरा जावा कार्यान्वयन है जो डुप्लिकेट को हटाता है।

public static int[] mergesort(int[] a, int[] b) {
    int[] c = new int[a.length + b.length];
    int i = 0, j = 0, k = 0, duplicateCount = 0;

    while (i < a.length || j < b.length) {
        if (i < a.length && j < b.length) {
            if (a[i] == b[j]) {
                c[k] = a[i];
                i++;j++;duplicateCount++;
            } else {
                c[k] = a[i] < b[j] ? a[i++] : b[j++];
            }
        } else if (i < a.length) {
            c[k] = a[i++];
        } else if (j < a.length) {
            c[k] = b[j++];
        }
        k++;
    }

    return Arrays.copyOf(c, c.length - duplicateCount);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.