দু'টি সাজানো অ্যারের মিলনে কীথের ক্ষুদ্রতম উপাদানটি কীভাবে খুঁজে পাবেন?


106

এটি একটি হোমওয়ার্ক প্রশ্ন। তারা বলছেন যে এটিগুলি O(logN + logM)কোথায় যায় Nএবং Mঅ্যারের দৈর্ঘ্য হয়।

অ্যারেগুলির নাম দিন aএবং b। স্পষ্টতই আমরা সমস্ত a[i]এবং b[i]যেখানে i> কে উপেক্ষা করতে পারি ।
প্রথমে তুলনা করা যাক a[k/2]এবং b[k/2]। যাক b[k/2]> a[k/2]। সুতরাং আমরা সমস্ত b[i], যেখানে i> কে / 2 ফেলে দিতে পারি।

এখন আমাদের কাছে সমস্ত রয়েছে a[i], যেখানে আমি <কে এবং সমস্ত b[i], যেখানে উত্তর << আমি / কে / 2 খুঁজে পেতে।

পরবর্তী পদক্ষেপ কি?


6
এই সমস্ত পদক্ষেপগুলি অ্যাসাইনমেন্টের অন্তর্ভুক্ত ছিল, বা উপরের পদক্ষেপগুলি কি আপনার অ্যালগরিদমের শুরু?
কেন্দ্রিক

18
উপরের ধাপগুলি আমার।
মাইকেল 19

হয় O(logN + logM)কেবলমাত্র kth উপাদান খুঁজে পেতে সময় লাগে উল্লেখ? ইউনিয়ন থেকে প্রাকপ্রসেসিং আগেই করা যেতে পারে?
ডেভিড ওয়েজার

1
@David। কোন প্রাকপ্রসেসিং আশা করা যায় না।
মাইকেল 19

3
অ্যারেতে নকলগুলি অনুমোদিত?
ডেভিড ওয়েজার

উত্তর:


48

আপনি এটি পেয়েছেন, কেবল চালিয়ে যান! এবং সূচীগুলি সম্পর্কে সাবধানতা অবলম্বন করুন ...

কিছুটা সহজ করার জন্য আমি ধরে নেব যে এন এবং এম> কে, তাই এখানে জটিলতা হ'ল (লগ কে), যা হে (লগ এন + লগ এম)।

সুডোকোড:

i = k/2
j = k - i
step = k/4
while step > 0
    if a[i-1] > b[j-1]
        i -= step
        j += step
    else
        i += step
        j -= step
    step /= 2

if a[i-1] > b[j-1]
    return a[i-1]
else
    return b[j-1]

বিক্ষোভের জন্য আপনি লুপ ইনভেরেন্ট আই + জ = কে ব্যবহার করতে পারেন তবে আমি আপনার সমস্ত হোমওয়ার্ক করব না :)


14
এটি প্রকৃত প্রমাণ নয়, তবে অ্যালগরিদমের পিছনে ধারণাটি হ'ল আমরা i + j = k বজায় রাখি এবং এরকম i এবং j খুঁজে পাই যাতে একটি [i-1] <b [j-1] <a [i] ( বা অন্যভাবে রাউন্ড)। এখন যেহেতু আমি 'এল' এর চেয়ে খ [জে -১] এর চেয়ে ছোট, এবং জে -১ উপাদানগুলিতে 'বি' খের চেয়ে ছোট [জে -১], বি [জে -১] আই + জে -১ + 1 = kth ক্ষুদ্রতম উপাদান। এই জাতীয় i, j আলগোরিদিম অ্যারেগুলিতে একটি দ্বৈতত্ত্বীয় অনুসন্ধান করে। বোধ হয়?
জুলিউস ওলান

8
ও (লগ কে) ও (লগ এন + লগ এম) কীভাবে আসবে?
রাজেন্দ্র উৎপল

7
অ্যারে 1 এর মানগুলি অ্যারে 2 এর মানগুলির আগে উপস্থিত হলে এটি কাজ করে না
জন কুর্লাক

3
আপনি কেন প্রথমে পদক্ষেপ হিসাবে k / 4 ব্যবহার করেছিলেন?
ম্যাগি

2
@ জনকুরলাক যেমন উল্লেখ করেছেন যে এটি মানগুলির জন্য কাজ করে না যেখানে পুরো একটি খ এর চেয়ে ছোট, দেখুন repl.it/HMYf/0
জেরেমি এস

69

আমি আশা করি আমি আপনার হোম ওয়ার্কটির উত্তর দিচ্ছি না কারণ এই প্রশ্নটি জিজ্ঞাসা করার এক বছর পেরিয়ে গেছে। এখানে একটি লেজ পুনরাবৃত্ত সমাধান রয়েছে যা লগ (লেন (এ) + লেন (খ)) সময় নেবে।

অনুমান: ইনপুটগুলি সঠিক। অর্থ্যাৎ কে এর পরিসীমা [0, লেন (ক) + লেন (খ)]

বেস কেসগুলি:

  • যদি অ্যারেরগুলির একটির দৈর্ঘ্য 0 হয় তবে উত্তরটি দ্বিতীয় অ্যারের kth উপাদান।

হ্রাস পদক্ষেপ:

  • মিড ইন্ডেক্স এর a+ মিড ইনডেক্স এর bচেয়ে কম হলেk
    • মাঝের উপাদানটি যদি মধ্য উপাদানের aচেয়ে বেশি হয় তবে bআমরা প্রথমার্ধটিকে অগ্রাহ্য করতে পারি b, সামঞ্জস্য করতে পারি k
    • অন্যথায় প্রথমার্ধ উপেক্ষা করুন a, সামঞ্জস্য করুন k
  • অন্যথায় যদি kমাঝারি সূচকগুলির যোগফলের চেয়ে কম হয় aএবং b:
    • মাঝের উপাদানটি যদি মধ্য উপাদানের aচেয়ে বেশি হয় তবে bআমরা দ্বিতীয়ার্ধের নিরাপদে উপেক্ষা করতে পারিa
    • অন্যথায় আমরা দ্বিতীয়ার্ধ উপেক্ষা করতে পারি b

কোড:

def kthlargest(arr1, arr2, k):
    if len(arr1) == 0:
        return arr2[k]
    elif len(arr2) == 0:
        return arr1[k]

    mida1 = len(arr1)/2
    mida2 = len(arr2)/2
    if mida1+mida2<k:
        if arr1[mida1]>arr2[mida2]:
            return kthlargest(arr1, arr2[mida2+1:], k-mida2-1)
        else:
            return kthlargest(arr1[mida1+1:], arr2, k-mida1-1)
    else:
        if arr1[mida1]>arr2[mida2]:
            return kthlargest(arr1[:mida1], arr2, k)
        else:
            return kthlargest(arr1, arr2[:mida2], k)

দয়া করে মনে রাখবেন যে আমার দ্রবণটি প্রতিটি কলে আরও ছোট অ্যারের নতুন কপি তৈরি করছে, এটি কেবলমাত্র মূল অ্যারেতে সূচনা এবং শেষ সূচকগুলি পেরিয়ে সহজেই নির্মূল করা যায়।


4
আপনি এটিকে কেন kthlargest()এটি (k+1)-তম ক্ষুদ্রতম উপাদানগুলি উদাহরণ হিসাবে উল্লেখ করেন, উদাহরণস্বরূপ, 1দ্বিতীয় 0,1,2,3ফাংশনটি হ'ল আপনার ফাংশনটি ফিরে আসে sorted(a+b)[k]
jfs

2
আমি আপনার কোডটি সি ++ তে রূপান্তর করেছি । এটি কাজ করছে বলে মনে হচ্ছে
jfs

1
আপনি দয়া করে ব্যাখ্যা করতে পারেন কেন ক এবং খ এর মধ্য সূচকের যোগফলের তুলনা করা গুরুত্বপূর্ণ?
ম্যাগি

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

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

34

অনেক লোক এই "Kth ক্ষুদ্রতম উপাদানটি দুটি বাছাই করা অ্যারে" প্রশ্নের উত্তর দিয়েছিলেন, তবে সাধারণত কেবলমাত্র সাধারণ ধারণা দিয়ে থাকে, একটি পরিষ্কার ওয়ার্কিং কোড বা সীমানা শর্ত বিশ্লেষণ নয়।

এখানে আমি সঠিকভাবে জাভা কোডটি সহ কিছু নবাগতকে বুঝতে সাহায্য করার জন্য আমি যেভাবে গিয়েছিলাম সে সম্পর্কে সাবধানতার সাথে এটি বিস্তারিতভাবে বর্ণনা করতে চাই। A1এবং যথাক্রমে এবং দৈর্ঘ্যের হিসাবে A2দুটি সাজানো আরোহী অ্যারে হয়। আমাদের সেই দুটি অ্যারের মিল থেকে কে-থতম ক্ষুদ্রতম উপাদানটি খুঁজে পাওয়া দরকার। এখানে আমরা যুক্তিসঙ্গতভাবে অনুমান , যা বোঝা এবং উভয় খালি রাখা যাবে না।size1size2(k > 0 && k <= size1 + size2)A1A2

প্রথমে একটি ধীর হে (কে) অ্যালগরিদম দিয়ে এই প্রশ্নটির সাথে যোগাযোগ করা যাক। পদ্ধতিটি হ'ল উভয় অ্যারের প্রথম উপাদানটির তুলনা করা A1[0]এবং A2[0]। ছোটটি নিন, A1[0]আমাদের পকেটে বলুন। তারপরে এবং এর A1[1]সাথে আরও তুলনা A2[0]করুন। আমাদের পকেট kউপাদান না পৌঁছানো পর্যন্ত এই ক্রিয়াটি পুনরাবৃত্তি করুন । খুব গুরুত্বপূর্ণ: প্রথম ধাপে, আমরা কেবল A1[0]আমাদের পকেটে প্রতিশ্রুতিবদ্ধ করতে পারি । আমরা অন্তর্ভুক্ত বা বাদ দিতে পারি না A2[0]!!!

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

private E kthSmallestSlowWithFault(int k) {
    int size1 = A1.length, size2 = A2.length;

    int index1 = 0, index2 = 0;
    // base case, k == 1
    if (k == 1) {
        if (size1 == 0) {
            return A2[index2];
        } else if (size2 == 0) {
            return A1[index1];
        } else if (A1[index1].compareTo(A2[index2]) < 0) {
            return A1[index1];
        } else {
            return A2[index2];
        }
    }

    /* in the next loop, we always assume there is one next element to compare with, so we can
     * commit to the smaller one. What if the last element is the kth one?
     */
    if (k == size1 + size2) {
        if (size1 == 0) {
            return A2[size2 - 1];
        } else if (size2 == 0) {
            return A1[size1 - 1];
        } else if (A1[size1 - 1].compareTo(A2[size2 - 1]) < 0) {
            return A1[size1 - 1];
        } else {
            return A2[size2 - 1];
        }
    }

    /*
     * only when k > 1, below loop will execute. In each loop, we commit to one element, till we
     * reach (index1 + index2 == k - 1) case. But the answer is not correct, always one element
     * ahead, because we didn't merge base case function into this loop yet.
     */
    int lastElementFromArray = 0;
    while (index1 + index2 < k - 1) {
        if (A1[index1].compareTo(A2[index2]) < 0) {
            index1++;
            lastElementFromArray = 1;
            // commit to one element from array A1, but that element is at (index1 - 1)!!!
        } else {
            index2++;
            lastElementFromArray = 2;
        }
    }
    if (lastElementFromArray == 1) {
        return A1[index1 - 1];
    } else {
        return A2[index2 - 1];
    }
}

সর্বাধিক শক্তিশালী ধারণাটি হ'ল প্রতিটি লুপে আমরা সর্বদা বেস কেস পদ্ধতির ব্যবহার করি। বর্তমানের ক্ষুদ্রতম উপাদানের প্রতি প্রতিশ্রুতিবদ্ধ হওয়ার পরে আমরা লক্ষ্যটির এক ধাপ কাছাকাছি পৌঁছাচ্ছি: কে-থতম ক্ষুদ্রতম উপাদান। মাঝে কখনও লাফিয়ে নিজেকে বিভ্রান্ত ও হারিয়ে ফেলবেন না!

উপরের কোড বেস কেসটি পর্যবেক্ষণ করে k == 1, k == size1+size2এবং এর সাথে একত্রিত করুন A1এবং A2উভয়ই খালি থাকতে পারবেন না। আমরা যুক্তিকে আরও সংক্ষিপ্ত শৈলীতে নীচে রূপান্তর করতে পারি।

এখানে একটি ধীর অথচ সঠিক ওয়ার্কিং কোড রয়েছে:

private E kthSmallestSlow(int k) {
    // System.out.println("this is an O(k) speed algorithm, very concise");
    int size1 = A1.length, size2 = A2.length;

    int index1 = 0, index2 = 0;
    while (index1 + index2 < k - 1) {
        if (size1 > index1 && (size2 <= index2 || A1[index1].compareTo(A2[index2]) < 0)) {
            index1++; // here we commit to original index1 element, not the increment one!!!
        } else {
            index2++;
        }
    }
    // below is the (index1 + index2 == k - 1) base case
    // also eliminate the risk of referring to an element outside of index boundary
    if (size1 > index1 && (size2 <= index2 || A1[index1].compareTo(A2[index2]) < 0)) {
        return A1[index1];
    } else {
        return A2[index2];
    }
}

এখন আমরা ও (লগ কে) এ দ্রুততর অ্যালগরিদম চালানোর চেষ্টা করতে পারি। একইভাবে, তুলনা A1[k/2]সঙ্গে A2[k/2]; যদি A1[k/2]ছোট হয়, তাহলে থেকে সকল উপাদান A1[0]থেকে A1[k/2]আমাদের পকেটে থাকা উচিত। ধারণাটি প্রতিটি লুপের মধ্যে কেবল একটি উপাদানকে প্রতিশ্রুতিবদ্ধ করা নয়; প্রথম ধাপে k/2উপাদান রয়েছে । আবার, আমরা যাইহোক অন্তর্ভুক্ত বা বাদ A2[0]দিতে পারি A2[k/2]না। সুতরাং প্রথম পদক্ষেপে, আমরা k/2উপাদানগুলির চেয়ে বেশি যেতে পারি না । দ্বিতীয় পদক্ষেপের জন্য, আমরা k/4উপাদানগুলির চেয়ে বেশি যেতে পারি না ...

প্রতিটি পদক্ষেপের পরে, আমরা কে-থ্রি উপাদানটির আরও কাছাকাছি যাই। একই সময়ে প্রতিটি পদক্ষেপ ছোট এবং আরও ছোট হয়, যতক্ষণ না আমরা পৌঁছায় (step == 1), যা (k-1 == index1+index2)। তারপরে আমরা আবার সহজ এবং শক্তিশালী বেস কেসটি উল্লেখ করতে পারি।

এখানে কার্যকারিতা সঠিক কোড:

private E kthSmallestFast(int k) {
    // System.out.println("this is an O(log k) speed algorithm with meaningful variables name");
    int size1 = A1.length, size2 = A2.length;

    int index1 = 0, index2 = 0, step = 0;
    while (index1 + index2 < k - 1) {
        step = (k - index1 - index2) / 2;
        int step1 = index1 + step;
        int step2 = index2 + step;
        if (size1 > step1 - 1
                && (size2 <= step2 - 1 || A1[step1 - 1].compareTo(A2[step2 - 1]) < 0)) {
            index1 = step1; // commit to element at index = step1 - 1
        } else {
            index2 = step2;
        }
    }
    // the base case of (index1 + index2 == k - 1)
    if (size1 > index1 && (size2 <= index2 || A1[index1].compareTo(A2[index2]) < 0)) {
        return A1[index1];
    } else {
        return A2[index2];
    }
}

কিছু লোক উদ্বিগ্ন হতে পারে (index1+index2)কে -১০ এর উপরে ঝাঁপিয়ে পড়লে কী হবে ? আমরা কি বেস কেস মিস করতে পারি (k-1 == index1+index2)? সেটা অসম্ভব. আপনি 0.5 + 0.25 + 0.125 যোগ করতে পারেন ... এবং আপনি কখনই 1 ছাড়িয়ে যাবেন না।

অবশ্যই উপরের কোডটি পুনরাবৃত্তিমূলক অ্যালগরিদমে রূপান্তর করা খুব সহজ:

private E kthSmallestFastRecur(int k, int index1, int index2, int size1, int size2) {
    // System.out.println("this is an O(log k) speed algorithm with meaningful variables name");

    // the base case of (index1 + index2 == k - 1)
    if (index1 + index2 == k - 1) {
        if (size1 > index1 && (size2 <= index2 || A1[index1].compareTo(A2[index2]) < 0)) {
            return A1[index1];
        } else {
            return A2[index2];
        }
    }

    int step = (k - index1 - index2) / 2;
    int step1 = index1 + step;
    int step2 = index2 + step;
    if (size1 > step1 - 1 && (size2 <= step2 - 1 || A1[step1 - 1].compareTo(A2[step2 - 1]) < 0)) {
        index1 = step1;
    } else {
        index2 = step2;
    }
    return kthSmallestFastRecur(k, index1, index2, size1, size2);
}

আশা করি উপরোক্ত বিশ্লেষণ এবং জাভা কোড আপনাকে বুঝতে সাহায্য করতে পারে। তবে কখনই আমার কোডটিকে আপনার হোমওয়ার্ক হিসাবে অনুলিপি করবেন না! চিয়ার্স;)


1
আপনার দুর্দান্ত ব্যাখ্যা এবং উত্তরের জন্য আপনাকে অনেক ধন্যবাদ, +1 :)
হেনগামেহ

প্রথম কোডে, else if (A1[size1 - 1].compareTo(A2[size2 - 1]) < 0) পরিবর্তে থাকা উচিত নয় else if (A1[size1 - 1].compareTo(A2[size2 - 1]) > 0)? (ইন kthSmallestSlowWithFault কোড)
Hengameh

আপনাকে ধন্যবাদ @ ফে। দুর্দান্ত ব্যাখ্যা। এই সমস্যাটি সম্পর্কে ইন্টারনেটে কতগুলি ভুল উত্তর ঘুরছে তা অবাক করে দেয়। এটি আরও বিস্ময়কর যে এই প্রশ্নটি সম্পর্কে তাঁর কাছে স্বীকৃত উত্তরটি সর্বদা ভুল। দেখে মনে হচ্ছে যে কেউ উত্তরগুলি পরীক্ষা করতে যত্ন করে না।
ক্যাপ্টেন ফোগেটি

কিছু পদক্ষেপের পরে ও (কে) সমাধানে কাট অফ হতে পারে (বলেছেন 15), কারণ পদক্ষেপের পরিধিটি খুব দ্রুত হ্রাস পায়।
আকাশ

1
পুনরাবৃত্ত কলগুলির কোনওটিতেই A1 বা A2 এর আকার হ্রাস হয় না।
আদিত্য জোশি

5

এখানে @ ল্যাম্বডাপিলগ্রিমের দ্রবণটির সি ++ পুনরাবৃত্ত সংস্করণ (সেখানে অ্যালগরিদমের ব্যাখ্যা দেখুন):

#include <cassert>
#include <iterator>

template<class RandomAccessIterator, class Compare>
typename std::iterator_traits<RandomAccessIterator>::value_type
nsmallest_iter(RandomAccessIterator firsta, RandomAccessIterator lasta,
               RandomAccessIterator firstb, RandomAccessIterator lastb,
               size_t n,
               Compare less) {
  assert(issorted(firsta, lasta, less) && issorted(firstb, lastb, less));
  for ( ; ; ) {
    assert(n < static_cast<size_t>((lasta - firsta) + (lastb - firstb)));
    if (firsta == lasta) return *(firstb + n);
    if (firstb == lastb) return *(firsta + n);

    size_t mida = (lasta - firsta) / 2;
    size_t midb = (lastb - firstb) / 2;
    if ((mida + midb) < n) {
      if (less(*(firstb + midb), *(firsta + mida))) {
        firstb += (midb + 1);
        n -= (midb + 1);
      }
      else {
        firsta += (mida + 1);
        n -= (mida + 1);
      }
    }
    else {
      if (less(*(firstb + midb), *(firsta + mida)))
        lasta = (firsta + mida);
      else
        lastb = (firstb + midb);
    }
  }
}

এটি সমস্ত 0 <= n < (size(a) + size(b))সূচির জন্য কাজ করে এবং এতে O(log(size(a)) + log(size(b)))জটিলতা রয়েছে।

উদাহরণ

#include <functional> // greater<>
#include <iostream>

#define SIZE(a) (sizeof(a) / sizeof(*a))

int main() {
  int a[] = {5,4,3};
  int b[] = {2,1,0};
  int k = 1; // find minimum value, the 1st smallest value in a,b

  int i = k - 1; // convert to zero-based indexing
  int v = nsmallest_iter(a, a + SIZE(a), b, b + SIZE(b),
                         SIZE(a)+SIZE(b)-1-i, std::greater<int>());
  std::cout << v << std::endl; // -> 0
  return v;
}

4

প্রথম ক্রমিক সংখ্যার জন্য আমার প্রচেষ্টা, 2 বাছাই করা অ্যারেতে kth নম্বর এবং n অনুসারে সাজানো অ্যারে:

// require() is recognizable by node.js but not by browser;
// for running/debugging in browser, put utils.js and this file in <script> elements,
if (typeof require === "function") require("./utils.js");

// Find K largest numbers in two sorted arrays.
function k_largest(a, b, c, k) {
    var sa = a.length;
    var sb = b.length;
    if (sa + sb < k) return -1;
    var i = 0;
    var j = sa - 1;
    var m = sb - 1;
    while (i < k && j >= 0 && m >= 0) {
        if (a[j] > b[m]) {
            c[i] = a[j];
            i++;
            j--;
        } else {
            c[i] = b[m];
            i++;
            m--;
        }
    }
    debug.log(2, "i: "+ i + ", j: " + j + ", m: " + m);
    if (i === k) {
        return 0;
    } else if (j < 0) {
        while (i < k) {
            c[i++] = b[m--];
        }
    } else {
        while (i < k) c[i++] = a[j--];
    }
    return 0;
}

// find k-th largest or smallest number in 2 sorted arrays.
function kth(a, b, kd, dir){
    sa = a.length; sb = b.length;
    if (kd<1 || sa+sb < kd){
        throw "Mission Impossible! I quit!";
    }

    var k;
    //finding the kd_th largest == finding the smallest k_th;
    if (dir === 1){ k = kd;
    } else if (dir === -1){ k = sa + sb - kd + 1;}
    else throw "Direction has to be 1 (smallest) or -1 (largest).";

    return find_kth(a, b, k, sa-1, 0, sb-1, 0);
}

// find k-th smallest number in 2 sorted arrays;
function find_kth(c, d, k, cmax, cmin, dmax, dmin){

    sc = cmax-cmin+1; sd = dmax-dmin+1; k0 = k; cmin0 = cmin; dmin0 = dmin;
    debug.log(2, "=k: " + k +", sc: " + sc + ", cmax: " + cmax +", cmin: " + cmin + ", sd: " + sd +", dmax: " + dmax + ", dmin: " + dmin);

    c_comp = k0-sc;
    if (c_comp <= 0){
        cmax = cmin0 + k0-1;
    } else {
        dmin = dmin0 + c_comp-1;
        k -= c_comp-1;
    }

    d_comp = k0-sd;
    if (d_comp <= 0){
        dmax = dmin0 + k0-1;
    } else {
        cmin = cmin0 + d_comp-1;
        k -= d_comp-1;
    }
    sc = cmax-cmin+1; sd = dmax-dmin+1;

    debug.log(2, "#k: " + k +", sc: " + sc + ", cmax: " + cmax +", cmin: " + cmin + ", sd: " + sd +", dmax: " + dmax + ", dmin: " + dmin + ", c_comp: " + c_comp + ", d_comp: " + d_comp);

    if (k===1) return (c[cmin]<d[dmin] ? c[cmin] : d[dmin]);
    if (k === sc+sd) return (c[cmax]>d[dmax] ? c[cmax] : d[dmax]);

    m = Math.floor((cmax+cmin)/2);
    n = Math.floor((dmax+dmin)/2);

    debug.log(2, "m: " + m + ", n: "+n+", c[m]: "+c[m]+", d[n]: "+d[n]);

    if (c[m]<d[n]){
        if (m === cmax){ // only 1 element in c;
            return d[dmin+k-1];
        }

        k_next = k-(m-cmin+1);
        return find_kth(c, d, k_next, cmax, m+1, dmax, dmin);
    } else {
        if (n === dmax){
            return c[cmin+k-1];
        }

        k_next = k-(n-dmin+1);
        return find_kth(c, d, k_next, cmax, cmin, dmax, n+1);
    }
}

function traverse_at(a, ae, h, l, k, at, worker, wp){
    var n = ae ? ae.length : 0;
    var get_node;
    switch (at){
        case "k": get_node = function(idx){
                var node = {};
                var pos = l[idx] + Math.floor(k/n) - 1;
                if (pos<l[idx]){ node.pos = l[idx]; }
                else if (pos > h[idx]){ node.pos = h[idx];}
                else{ node.pos = pos; }

                node.idx = idx;
                node.val = a[idx][node.pos];
                debug.log(6, "pos: "+pos+"\nnode =");
                debug.log(6, node);
                return node;
            };
            break;
        case "l": get_node = function(idx){
                debug.log(6, "a["+idx+"][l["+idx+"]]: "+a[idx][l[idx]]);
                return a[idx][l[idx]];
            };
            break;
        case "h": get_node = function(idx){
                debug.log(6, "a["+idx+"][h["+idx+"]]: "+a[idx][h[idx]]);
                return a[idx][h[idx]];
            };
            break;
        case "s": get_node = function(idx){
                debug.log(6, "h["+idx+"]-l["+idx+"]+1: "+(h[idx] - l[idx] + 1));
                return h[idx] - l[idx] + 1;
            };
            break;
        default: get_node = function(){
                debug.log(1, "!!! Exception: get_node() returns null.");
                return null;
            };
            break;
    }

    worker.init();

    debug.log(6, "--* traverse_at() *--");

    var i;
    if (!wp){
        for (i=0; i<n; i++){
            worker.work(get_node(ae[i]));
        }    
    } else {
        for (i=0; i<n; i++){
            worker.work(get_node(ae[i]), wp);
        }
    }

    return worker.getResult();
}

sumKeeper = function(){
    var res = 0;
    return {
        init     : function(){ res = 0;},
        getResult: function(){
                debug.log(5, "@@ sumKeeper.getResult: returning: "+res);
                return res;
            },
        work     : function(node){ if (node!==null) res += node;}
    };
}();

maxPicker = function(){
    var res = null;
    return {
        init     : function(){ res = null;},
        getResult: function(){
                debug.log(5, "@@ maxPicker.getResult: returning: "+res);
                return res;
            },
        work     : function(node){
            if (res === null){ res = node;}
            else if (node!==null && node > res){ res = node;}
        }
    };    
}();

minPicker = function(){
    var res = null;
    return {
        init     : function(){ res = null;},
        getResult: function(){
                debug.log(5, "@@ minPicker.getResult: returning: ");
                debug.log(5, res);
                return res;
            },
        work     : function(node){
            if (res === null && node !== null){ res = node;}
            else if (node!==null &&
                node.val !==undefined &&
                node.val < res.val){ res = node; }
            else if (node!==null && node < res){ res = node;}
        }
    };  
}();

// find k-th smallest number in n sorted arrays;
// need to consider the case where some of the subarrays are taken out of the selection;
function kth_n(a, ae, k, h, l){
    var n = ae.length;
    debug.log(2, "------**  kth_n()  **-------");
    debug.log(2, "n: " +n+", k: " + k);
    debug.log(2, "ae: ["+ae+"],  len: "+ae.length);
    debug.log(2, "h: [" + h + "]");
    debug.log(2, "l: [" + l + "]");

    for (var i=0; i<n; i++){
        if (h[ae[i]]-l[ae[i]]+1>k) h[ae[i]]=l[ae[i]]+k-1;
    }
    debug.log(3, "--after reduction --");
    debug.log(3, "h: [" + h + "]");
    debug.log(3, "l: [" + l + "]");

    if (n === 1)
        return a[ae[0]][k-1]; 
    if (k === 1)
        return traverse_at(a, ae, h, l, k, "l", minPicker);
    if (k === traverse_at(a, ae, h, l, k, "s", sumKeeper))
        return traverse_at(a, ae, h, l, k, "h", maxPicker);

    var kn = traverse_at(a, ae, h, l, k, "k", minPicker);
    debug.log(3, "kn: ");
    debug.log(3, kn);

    var idx = kn.idx;
    debug.log(3, "last: k: "+k+", l["+kn.idx+"]: "+l[idx]);
    k -= kn.pos - l[idx] + 1;
    l[idx] = kn.pos + 1;
    debug.log(3, "next: "+"k: "+k+", l["+kn.idx+"]: "+l[idx]);
    if (h[idx]<l[idx]){ // all elements in a[idx] selected;
        //remove a[idx] from the arrays.
        debug.log(4, "All elements selected in a["+idx+"].");
        debug.log(5, "last ae: ["+ae+"]");
        ae.splice(ae.indexOf(idx), 1);
        h[idx] = l[idx] = "_"; // For display purpose only.
        debug.log(5, "next ae: ["+ae+"]");
    }

    return kth_n(a, ae, k, h, l);
}

function find_kth_in_arrays(a, k){

    if (!a || a.length<1 || k<1) throw "Mission Impossible!";

    var ae=[], h=[], l=[], n=0, s, ts=0;
    for (var i=0; i<a.length; i++){
        s = a[i] && a[i].length;
        if (s>0){
            ae.push(i); h.push(s-1); l.push(0);
            ts+=s;
        }
    }

    if (k>ts) throw "Too few elements to choose from!";

    return kth_n(a, ae, k, h, l);
}

/////////////////////////////////////////////////////
// tests
// To show everything: use 6.
debug.setLevel(1);

var a = [2, 3, 5, 7, 89, 223, 225, 667];
var b = [323, 555, 655, 673];
//var b = [99];
var c = [];

debug.log(1, "a = (len: " + a.length + ")");
debug.log(1, a);
debug.log(1, "b = (len: " + b.length + ")");
debug.log(1, b);

for (var k=1; k<a.length+b.length+1; k++){
    debug.log(1, "================== k: " + k + "=====================");

    if (k_largest(a, b, c, k) === 0 ){
      debug.log(1, "c = (len: "+c.length+")");
      debug.log(1, c);
    }

    try{
        result = kth(a, b, k, -1);
        debug.log(1, "===== The " + k + "-th largest number: " + result);
    } catch (e) {
        debug.log(0, "Error message from kth(): " + e);
    }
    debug.log("==================================================");
}

debug.log(1, "################# Now for the n sorted arrays ######################");
debug.log(1, "####################################################################");

x = [[1, 3, 5, 7, 9],
     [-2, 4, 6, 8, 10, 12],
     [8, 20, 33, 212, 310, 311, 623],
     [8],
     [0, 100, 700],
     [300],
     [],
     null];

debug.log(1, "x = (len: "+x.length+")");
debug.log(1, x);

for (var i=0, num=0; i<x.length; i++){
    if (x[i]!== null) num += x[i].length;
}
debug.log(1, "totoal number of elements: "+num);

// to test k in specific ranges:
var start = 0, end = 25;
for (k=start; k<end; k++){
    debug.log(1, "=========================== k: " + k + "===========================");

    try{
        result = find_kth_in_arrays(x, k);
        debug.log(1, "====== The " + k + "-th smallest number: " + result);
    } catch (e) {
        debug.log(1, "Error message from find_kth_in_arrays: " + e);
    }
    debug.log(1, "=================================================================");
}
debug.log(1, "x = (len: "+x.length+")");
debug.log(1, x);
debug.log(1, "totoal number of elements: "+num);

ডিবাগ ব্যবহারের সাথে সম্পূর্ণ কোডটি এখানে পাওয়া যাবে: https://github.com/brainclone/teasers/tree/master/kth


3

জুলস ওলিওনের সমাধানের ভিত্তিতে আমার কোড এখানে রয়েছে:

int getNth(vector<int>& v1, vector<int>& v2, int n)
{
    int step = n / 4;

    int i1 = n / 2;
    int i2 = n - i1;

    while(!(v2[i2] >= v1[i1 - 1] && v1[i1] > v2[i2 - 1]))
    {                   
        if (v1[i1 - 1] >= v2[i2 - 1])
        {
            i1 -= step;
            i2 += step;
        }
        else
        {
            i1 += step;
            i2 -= step;
        }

        step /= 2;
        if (!step) step = 1;
    }

    if (v1[i1 - 1] >= v2[i2 - 1])
        return v1[i1 - 1];
    else
        return v2[i2 - 1];
}

int main()  
{  
    int a1[] = {1,2,3,4,5,6,7,8,9};
    int a2[] = {4,6,8,10,12};

    //int a1[] = {1,2,3,4,5,6,7,8,9};
    //int a2[] = {4,6,8,10,12};

    //int a1[] = {1,7,9,10,30};
    //int a2[] = {3,5,8,11};
    vector<int> v1(a1, a1+9);
    vector<int> v2(a2, a2+5);


    cout << getNth(v1, v2, 5);
    return 0;  
}  

1
এটি কিছু ক্ষেত্রে কাজ করবে না। উদাহরণস্বরূপ, int a2 [] = {1,2,3,4, 5}; int a1 [] = {5,6,8,10,12}; getNth (এ 1, এ 2, 7) অ্যারের সূচি সীমা ছাড়িয়ে যাবে।
জয়

2

সিতে আমার বাস্তবায়নটি এখানে রয়েছে, আপনি @ অ্যালগরিদমের জন্য জুলস ওলিয়নের ব্যাখ্যাগুলি দেখুন: অ্যালগরিদমের পিছনে ধারণাটি হল আমরা i + j = k বজায় রেখেছি এবং এরকম আই এবং জে খুঁজে পাই যাতে একটি [i-1] <বি [জে -১] <ক [আই] (বা অন্যভাবে রাউন্ড)। এখন যেহেতু আমি 'এল' এর চেয়ে খ [জে -১] এর চেয়ে ছোট, এবং জে -১ উপাদানগুলিতে 'বি' খের চেয়ে ছোট [জে -১], বি [জে -১] আই + জে -১ + 1 = kth ক্ষুদ্রতম উপাদান। যেমন i, j আলগোরিদিম অ্যারেগুলিতে একটি দ্বৈতত্ত্বীয় অনুসন্ধান করে।

int find_k(int A[], int m, int B[], int n, int k) {
   if (m <= 0 )return B[k-1];
   else if (n <= 0) return A[k-1];
   int i =  ( m/double (m + n))  * (k-1);
   if (i < m-1 && i<k-1) ++i;
   int j = k - 1 - i;

   int Ai_1 = (i > 0) ? A[i-1] : INT_MIN, Ai = (i<m)?A[i]:INT_MAX;
   int Bj_1 = (j > 0) ? B[j-1] : INT_MIN, Bj = (j<n)?B[j]:INT_MAX;
   if (Ai >= Bj_1 && Ai <= Bj) {
       return Ai;
   } else if (Bj >= Ai_1 && Bj <= Ai) {
       return Bj;
   }
   if (Ai < Bj_1) { // the answer can't be within A[0,...,i]
       return find_k(A+i+1, m-i-1, B, n, j);
   } else { // the answer can't be within A[0,...,i]
       return find_k(A, m, B+j+1, n-j-1, i);
   }
 }

2

এখানে আমার সমাধান। সি ++ কোডটি kth ক্ষুদ্রতম মানের পাশাপাশি একটি লুপ ব্যবহার করে kth ক্ষুদ্রতম মান পেতে পুনরাবৃত্তির সংখ্যা প্রিন্ট করে, যা আমার মতে লগ (কে) এর ক্রম অনুসারে। কোডটি অবশ্য প্রথম অ্যারের দৈর্ঘ্যের চেয়ে কম হওয়া উচিত যা একটি সীমাবদ্ধতা।

#include <iostream>
#include <vector>
#include<math.h>
using namespace std;

template<typename comparable>
comparable kthSmallest(vector<comparable> & a, vector<comparable> & b, int k){

int idx1; // Index in the first array a
int idx2; // Index in the second array b
comparable maxVal, minValPlus;
float iter = k;
int numIterations = 0;

if(k > a.size()){ // Checks if k is larger than the size of first array
    cout << " k is larger than the first array" << endl;
    return -1;
}
else{ // If all conditions are satisfied, initialize the indexes
    idx1 = k - 1;
    idx2 = -1;
}

for ( ; ; ){
    numIterations ++;
    if(idx2 == -1 || b[idx2] <= a[idx1] ){
        maxVal = a[idx1];
        minValPlus = b[idx2 + 1];
        idx1 = idx1 - ceil(iter/2); // Binary search
        idx2 = k - idx1 - 2; // Ensures sum of indices  = k - 2
    }
    else{
        maxVal = b[idx2];
        minValPlus = a[idx1 + 1];
        idx2 = idx2 - ceil(iter/2); // Binary search
        idx1 = k - idx2 - 2; // Ensures sum of indices  = k - 2
    }
    if(minValPlus >= maxVal){ // Check if kth smallest value has been found
        cout << "The number of iterations to find the " << k << "(th) smallest value is    " << numIterations << endl;
        return maxVal;

    }
    else
        iter/=2; // Reduce search space of binary search
   }
}

int main(){
//Test Cases
    vector<int> a = {2, 4, 9, 15, 22, 34, 45, 55, 62, 67, 78, 85};
    vector<int> b = {1, 3, 6, 8, 11, 13, 15, 20, 56, 67, 89};
    // Input k < a.size()
    int kthSmallestVal;
    for (int k = 1; k <= a.size() ; k++){
        kthSmallestVal = kthSmallest<int>( a ,b ,k );
        cout << k <<" (th) smallest Value is " << kthSmallestVal << endl << endl << endl;
    }
}

1

উপরে প্রদত্ত প্রথম সিউডো কোড, অনেকগুলি মানের জন্য কাজ করে না। উদাহরণস্বরূপ, এখানে দুটি অ্যারে রয়েছে। int [] a = {1, 5, 6, 8, 9, 11, 15, 17, 19}; int [] খ = {4, 7, 8, 13, 15, 18, 20, 24, 26};

এটি এতে কে = 3 এবং কে = 9 এর জন্য কাজ করে না। আমার আর একটি সমাধান আছে। এটি নীচে দেওয়া হয়েছে।

private static void traverse(int pt, int len) {
int temp = 0;

if (len == 1) {
    int val = 0;
    while (k - (pt + 1) - 1 > -1 && M[pt] < N[k - (pt + 1) - 1]) {

    if (val == 0)
        val = M[pt] < N[k - (pt + 1) - 1] ? N[k - (pt + 1) - 1]
            : M[pt];
    else {
        int t = M[pt] < N[k - (pt + 1) - 1] ? N[k - (pt + 1) - 1]
            : M[pt];
        val = val < t ? val : t;

    }

    ++pt;
    }

    if (val == 0)
    val = M[pt] < N[k - (pt + 1) - 1] ? N[k - (pt + 1) - 1] : M[pt];

    System.out.println(val);
    return;
}

temp = len / 2;

if (M[pt + temp - 1] < N[k - (pt + temp) - 1]) {
    traverse(pt + temp, temp);

} else {
    traverse(pt, temp);
}

}

তবে ... এটি কে = 5 এর জন্যও কাজ করছে না। এখানে কে-এর সম / বিজোড় ক্যাচ রয়েছে যা এটিকে সহজ হতে দিচ্ছে না।


1
public class KthSmallestInSortedArray {

    public static void main(String[] args) {
        int a1[] = {2, 3, 10, 11, 43, 56},
                a2[] = {120, 13, 14, 24, 34, 36},
                k = 4;

        System.out.println(findKthElement(a1, a2, k));

    }

    private static int findKthElement(int a1[], int a2[], int k) {

        /** Checking k must less than sum of length of both array **/
        if (a1.length + a2.length < k) {
            throw new IllegalArgumentException();
        }

        /** K must be greater than zero **/
        if (k <= 0) {
            throw new IllegalArgumentException();
        }

        /**
         * Finding begin, l and end such that
         * begin <= l < end
         * a1[0].....a1[l-1] and
         * a2[0]....a2[k-l-1] are the smallest k numbers
         */
        int begin = Math.max(0, k - a2.length);
        int end = Math.min(a1.length, k);

        while (begin < end) {
            int l = begin + (end - begin) / 2;

            /** Can we include a1[l] in the k smallest numbers */
            if ((l < a1.length) &&
                    (k - l > 0) &&
                    (a1[l] < a2[k - l - 1])) {

                begin = l + 1;

            } else if ((l > 0) &&
                    (k - l < a2.length) &&
                    (a1[l - 1] > a2[k - 1])) {

                /**
                 * This is the case where we can discard
                 * a[l-1] from the set of k smallest numbers
                 */
                end = l;

            } else {

                /**
                 * We found our answer since both inequalities were
                 * false
                 */
                begin = l;
                break;
            }
        }

        if (begin == 0) {
            return a2[k - 1];
        } else if (begin == k) {
            return a1[k - 1];
        } else {
            return Math.max(a1[begin - 1], a2[k - begin - 1]);
        }
    }
}

1

জাভাতে আমার সলিউশন এখানে। এটি আরও অনুকূলিত করার চেষ্টা করবে

  public class FindKLargestTwoSortedArray {

    public static void main(String[] args) {
        int[] arr1 = { 10, 20, 40, 80 };
        int[] arr2 = { 15, 35, 50, 75 };

    FindKLargestTwoSortedArray(arr1, 0, arr1.length - 1, arr2, 0,
            arr2.length - 1, 6);
    }


    public static void FindKLargestTwoSortedArray(int[] arr1, int start1,
            int end1, int[] arr2, int start2, int end2, int k) {

        if ((start1 <= end1 && start1 >= 0 && end1 < arr1.length)
                && (start2 <= end2 && start2 >= 0 && end2 < arr2.length)) {

            int midIndex1 = (start1 + (k - 1) / 2);
            midIndex1 = midIndex1 >= arr1.length ? arr1.length - 1 : midIndex1;
            int midIndex2 = (start2 + (k - 1) / 2);
            midIndex2 = midIndex2 >= arr2.length ? arr2.length - 1 : midIndex2;


            if (arr1[midIndex1] == arr2[midIndex2]) {
                System.out.println("element is " + arr1[midIndex1]);
            } else if (arr1[midIndex1] < arr2[midIndex2]) {

                if (k == 1) {
                    System.out.println("element is " + arr1[midIndex1]);
                    return;
                } else if (k == 2) {
                    System.out.println("element is " + arr2[midIndex2]);
                    return;
                }else if (midIndex1 == arr1.length-1 || midIndex2 == arr2.length-1 ) {
                    if(k==(arr1.length+arr2.length)){
                    System.out.println("element is " + arr2[midIndex2]);
                    return;
                    }else if(k==(arr1.length+arr2.length)-1){
                        System.out.println("element is " + arr1[midIndex1]);
                        return;
                    }

                }

                int remainingElementToSearch = k - (midIndex1-start1);
                FindKLargestTwoSortedArray(
                        arr1,
                        midIndex1,
                        (midIndex1 + remainingElementToSearch) >= arr1.length ? arr1.length-1
                                : (midIndex1 + remainingElementToSearch), arr2,
                        start2, midIndex2, remainingElementToSearch);

            } else if (arr1[midIndex1] > arr2[midIndex2]) {
                FindKLargestTwoSortedArray(arr2, start2, end2, arr1, start1,
                        end1, k);
            }

        } else {
            return;
        }

    }
}

এটি আলগো থেকে দুর্দান্ত ইউটিউব ভিডিওতে অনুপ্রাণিত


1

কোড জটিলতায় লগ (লগ (এন) + লগ (এম))

কোডের লিংক (লগ (এন) * লগ (এম))

বাস্তবায়ন(লগ (এন) + লগ (এম)) সমাধানের

আমি সমস্যার সাথে আমার ব্যাখ্যা যুক্ত করতে চাই। এটি একটি ক্লাসিক সমস্যা যেখানে আমাদের দুটি অ্যারে বাছাই করা হয়েছে তা ব্যবহার করতে হবে। আমাদের আকার sz1 এর দুটি সাজানো অ্যারে অ্যারে 1 এবং আকারের জেড 2 এর অ্যারে 2 দেওয়া হয়েছে

ক) ধরুন যদি

কে বৈধ কিনা তা পরীক্ষা করা হচ্ছে

কে হল> (sz1 + sz2)

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

এজ কেস পরিচালনা করা

আমরা কে = 1,2 এবং কে = (sz1 + sz2-1), (sz1 + sz2) ইত্যাদির প্রান্তের কেসগুলি কভার করার জন্য শেষে এবং ইনফিনিটি মানগুলি অনুসারে উভয় অ্যারে যুক্ত করব +

এখন উভয় অ্যারে আকার (sz1 +2) এবং (sz2 +2) যথাক্রমে

প্রধান অ্যালগরিদম

এখন, আমরা আর্ট 1-তে বাইনারি অনুসন্ধান করব eআর 1 তে বাইনারি অনুসন্ধান করব আমি সূচক i, startIndex <= i <= endIndex সন্ধান করব

যেমন যদি আমরা সীমাবদ্ধতা {(i + j) = k using ব্যবহার করে আরআর 2 তে সংশ্লিষ্ট সূচক জে দেখতে পাই, তবে যদি

যদি (আরআর 2 [জে -1] <আরআর 1 [আই] <আরআর 2 [জে]) হয় তবে আরআর 1 [i] কেথ ক্ষুদ্রতম (কেস 1)

অন্যথায় যদি (arr1 [i-1] <arr2 [j] <arr1 [i]) হয় , তবে arr2 [i] হল kth সবচেয়ে ছোট (কেস 2)

অন্যথায় হয় arr1 [i] <arr2 [j-1] <arr2 [j] arr2 (কেস 3)

বা এআর 2 [জে -১] <আরআর 2 [জে] <আরআর 1 [আই] (কেস ৪)

যেহেতু আমরা জানি যে Kth ক্ষুদ্রতম এলিমেন্টের তুলনায় (কে -1) উপাদান রয়েছে উভয় অ্যারে রাইটের মিলের ? সুতরাং,

ইন Case1 আমরা যেটা করেছি সেটা আমরা নিশ্চিত (ট-1) ছোট উপাদানের একটি মোট arr1 করার আছে [আমি] কারণ উপাদানের arr1 [আমি] মধ্যে arr1 অ্যারের ই-1 টি সংখ্যা তুলনায় আমরা জানি (arr2 হল [চেয়ে ছোট j-1] <arr1 [i] <arr2 [j]) এবং arr2 এ arr1 এর চেয়ে ছোট উপাদানগুলির সংখ্যা [i] j-1 কারণ জে (i-1) + (j-1) = (কে ব্যবহার করে পাওয়া গেছে) -1) সুতরাং kth ক্ষুদ্রতম উপাদানটি হবে arr1 [i]

তবে উত্তরটি সর্বদা প্রথম অ্যারে থেকে না আসতে পারে অর্থাৎ এআর 1 তাই আমরা কেস 2 এর জন্য যাচাই করেছিলাম যা 1 এর মতোই সন্তুষ্ট কারণ কারণ (আই -1) + (জে 1) = (কে -1)। এখন যদি আমাদের কাছে (আরআর 1 [আই -1] <আরআর 2 [জে] <এআর 1 [i]) থাকে তবে আমাদের উভয় অ্যারে মিলিয়ে মোট কে -1 উপাদান রয়েছে যার ফলে এটিই এর ক্ষুদ্রতম উপাদান।

ইন case3 , কেস 1 বা কেস 2 কোন এটি গঠন, আমরা আমি বাড়ায় এবং ঞ বাধ্যতা ব্যবহার অনুযায়ী পাওয়া যাবে দরকার {(আমি + ঞ) = ট} ডান অংশ বাইনারি অনুসন্ধান পদক্ষেপের মাধ্যমে অর্থাত অর্থাত করতে startIndex = middleIndex

ইন case4 , কেস 1 বা কেস 2 কোন এটি গঠন, আমরা আমি হ্রাস এবং J {(আমি + ঞ) = ট} বাধ্যতা বাম অংশ বাইনারি অনুসন্ধান পদক্ষেপের মাধ্যমে অর্থাত অর্থাত করতে endIndex = middleIndex ব্যবহার অনুযায়ী পাওয়া যাবে দরকার ।

এখন আরআর 1-এর সাথে বাইনারি অনুসন্ধানের শুরুতে স্টার্টইন্ডেক্স = 1 এবং এন্ডআইডেক্স = ?? কীভাবে শুরু করবেন এবং কীভাবে শুরু করবেন তা সিদ্ধান্ত নিতে হবে We আমাদের সিদ্ধান্ত নেওয়া দরকার।

যদি k> sz1, endIndex = (sz1 + 1), অন্যথায় endIndex = কে;

কারণ যদি কে প্রথম অ্যারের আকারের চেয়ে বড় হয় তবে আমাদের পুরো অ্যারে অ্যারে 1 এর উপর বাইনারি অনুসন্ধান করতে হতে পারে অন্যথায় আমাদের কেবল এর প্রথম কে উপাদানগুলি নেওয়া দরকার কারণ sz1-k উপাদানগুলি কখনই ক্ষুদ্রতম গণনায় অবদান রাখতে পারে না।

কোডে নীচে দেখানো হয়েছে

// Complexity    O(log(n)+log(m))

#include<bits/stdc++.h>
using namespace std;
#define f(i,x,y) for(int i = (x);i < (y);++i)
#define F(i,x,y) for(int i = (x);i > (y);--i)
int max(int a,int b){return (a > b?a:b);}
int min(int a,int b){return (a < b?a:b);}
int mod(int a){return (a > 0?a:((-1)*(a)));}
#define INF 1000000




int func(int *arr1,int *arr2,int sz1,int sz2,int k)

{

if((k <= (sz1+sz2))&&(k > 0))

{
int s = 1,e,i,j;
if(k > sz1)e = sz1+1;
else e = k;
while((e-s)>1)
{
  i = (e+s)/2;
  j = ((k-1)-(i-1)); 
  j++;
  if(j > (sz2+1)){s = i;}
  else if((arr1[i] >= arr2[j-1])&&(arr1[i] <= arr2[j]))return arr1[i];
  else if((arr2[j] >= arr1[i-1])&&(arr2[j] <= arr1[i]))return arr2[j];
  else if(arr1[i] < arr2[j-1]){s = i;}
  else if(arr1[i] > arr2[j]){e = i;}
  else {;}
}
i = e,j = ((k-1)-(i-1));j++;
if((arr1[i] >= arr2[j-1])&&(arr1[i] <= arr2[j]))return arr1[i];
else if((arr2[j] >= arr1[i-1])&&(arr2[j] <= arr1[i]))return arr2[j];
else
{
  i = s,j = ((k-1)-(i-1));j++;
  if((arr1[i] >= arr2[j-1])&&(arr1[i] <= arr2[j]))return arr1[i];
  else return arr2[j];
}

  }

 else

{
cout << "Data Invalid" << endl;
return -INF;

}

}





int main()

{
int n,m,k;
cin >> n >> m >> k;
int arr1[n+2];
int arr2[m+2];
f(i,1,n+1)
cin >> arr1[i];
f(i,1,m+1)
cin >> arr2[i];
arr1[0] = -INF;
arr2[0] = -INF;
  arr1[n+1] = +INF;  
arr2[m+1] = +INF; 
int val = func(arr1,arr2,n,m,k);
if(val != -INF)cout << val << endl;   
return 0;

}

জটিলতার সমাধানের জন্য (লগ (এন) * লগ (এম))

কেবল আমি এই সত্যটির সুবিধাটি ব্যবহার করেই মিস করেছি যে প্রতিটির জন্য আমি জে বাধা using (আই -1) + (জে -1) = (কে -1) ব্যবহার করে খুঁজে পেতে পারি} সুতরাং প্রতিটি ii এর জন্য দ্বিতীয় অ্যারেতে বাইনারি অনুসন্ধান প্রয়োগ করা হয়েছিল জে যেমন যে arr2 [j] <= arr1 [i] খুঁজে পেতে। সুতরাং এই সমাধানটি আরও অনুকূলিত করা যেতে পারে


1

মূলত, এই পদ্ধতির মাধ্যমে আপনি প্রতিটি পদক্ষেপে k / 2 উপাদানগুলি বাতিল করতে পারেন। কে পুনরায় অবিচ্ছিন্নভাবে কে => কে / 2 => কে / 4 => থেকে পরিবর্তন হবে ... এটি 1 নাগাদ হওয়া পর্যন্ত। সুতরাং, সময় জটিলতা হ'ল (লগক)

কে = 1 এ, আমরা দুটি অ্যারের চেয়ে কম পাই।

নিম্নলিখিত কোডটি জাভাতে রয়েছে। দয়া করে নোট করুন যে আমরা সূচীগুলি থেকে কোডে 1 (-1) বিয়োগ করছি কারণ জাভা অ্যারের সূচকটি 0 থেকে শুরু হয় না, উদাহরণস্বরূপ 1 । k = 3 একটি অ্যারের ২ য় সূচকে উপাদান দ্বারা প্রতিনিধিত্ব করা হয়।

private int kthElement(int[] arr1, int[] arr2, int k) {
        if (k < 1 || k > (arr1.length + arr2.length))
            return -1;
        return helper(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, k);
    }


private int helper(int[] arr1, int low1, int high1, int[] arr2, int low2, int high2, int k) {
    if (low1 > high1) {
        return arr2[low2 + k - 1];
    } else if (low2 > high2) {
        return arr1[low1 + k - 1];
    }
    if (k == 1) {
        return Math.min(arr1[low1], arr2[low2]);
    }
    int i = Math.min(low1 + k / 2, high1 + 1);
    int j = Math.min(low2 + k / 2, high2 + 1);
    if (arr1[i - 1] > arr2[j - 1]) {
        return helper(arr1, low1, high1, arr2, j, high2, k - (j - low2));
    } else {
        return helper(arr1, i, high1, arr2, low2, high2, k - (i - low1));
    }
}

1
#include <bits/stdc++.h>
using namespace std;

int findKthElement(int a[],int start1,int end1,int b[],int start2,int end2,int k){

    if(start1 >= end1)return b[start2+k-1];
    if(start2 >= end2)return a[start1+k-1];
    if(k==1)return min(a[start1],b[start2]);
    int aMax = INT_MAX;
    int bMax = INT_MAX;
    if(start1+k/2-1 < end1) aMax = a[start1 + k/2 - 1];
    if(start2+k/2-1 < end2) bMax = b[start2 + k/2 - 1];

    if(aMax > bMax){
        return findKthElement(a,start1,end1,b,start2+k/2,end2,k-k/2);
    }
    else{
        return findKthElement(a,start1 + k/2,end1,b,start2,end2,k-k/2);
    }
}

int main(void){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        cout<<"Enter the size of 1st Array"<<endl;
        cin>>n;
        int arr[n];
        cout<<"Enter the Element of 1st Array"<<endl;
        for(int i = 0;i<n;i++){
            cin>>arr[i];
        }
        cout<<"Enter the size of 2nd Array"<<endl;
        cin>>m;
        int arr1[m];
        cout<<"Enter the Element of 2nd Array"<<endl;
        for(int i = 0;i<m;i++){
            cin>>arr1[i];
        }
        cout<<"Enter The Value of K";
        cin>>k;
        sort(arr,arr+n);
        sort(arr1,arr1+m);
        cout<<findKthElement(arr,0,n,arr1,0,m,k)<<endl;
    }

    return 0;
}

সময় জটিলতা হ'ল ল (লগ (মিনিট (এন, মি)))


1

আমি এখানে যে উত্তরগুলি পেয়েছি তা বেশিরভাগই উভয় অ্যারেতে ফোকাস করে। যদিও এটি ভাল তবে এটি প্রয়োগ করা আরও শক্ত কারণ আমাদের প্রচুর যত্ন নেওয়া দরকার edge এছাড়াও বেশিরভাগ বাস্তবায়ন পুনরাবৃত্ত হয় যা পুনরাবৃত্তি স্ট্যাকের স্পেস জটিলতা যুক্ত করে। সুতরাং উভয় অ্যারেগুলিতে মনোনিবেশ করার পরিবর্তে আমি ঠিক করেছি যে কেবল ছোট অ্যারেতে ফোকাস করব এবং কেবল ছোট অ্যারেতে বাইনারি অনুসন্ধান করব এবং প্রথম অ্যারেতে পয়েন্টারের মানের উপর ভিত্তি করে দ্বিতীয় অ্যারের জন্য পয়েন্টারটি সামঞ্জস্য করব। নিম্নলিখিত বাস্তবায়ন দ্বারা, আমাদের স্পেস জটিলতার O(log(min(n,m))সাথে O(1)জটিলতা রয়েছে।

    public static int kth_two_sorted(int []a, int b[],int k){
    if(a.length > b.length){
        return kth_two_sorted(b,a,k);
    }
    if(a.length + a.length < k){
        throw new RuntimeException("wrong argument");
    }
    int low = 0;
    int high = k;
    if(a.length <= k){
        high = a.length-1;
    }
    while(low <= high){
        int sizeA = low+(high - low)/2;
        int sizeB = k - sizeA;
        boolean shrinkLeft = false;
        boolean extendRight = false;
        if(sizeA != 0){
            if(sizeB !=b.length){
                if(a[sizeA-1] > b[sizeB]){
                    shrinkLeft = true;
                    high = sizeA-1;
                }
            }
        }
        if(sizeA!=a.length){
            if(sizeB!=0){
                if(a[sizeA] < b[sizeB-1]){
                    extendRight = true;
                    low = sizeA;
                }
            }
        }
        if(!shrinkLeft && !extendRight){
            return Math.max(a[sizeA-1],b[sizeB-1]) ;
        }
    }
    throw  new IllegalArgumentException("we can't be here");
}

[low, high]অ্যারে জন্য আমাদের একটি ব্যাপ্তি রয়েছে aএবং অ্যালগরিদম দিয়ে আরও এগিয়ে যাওয়ার সাথে সাথে আমরা এই ব্যাপ্তিকে সংকীর্ণ করি। sizeAদেখায় কিভাবে থেকে আইটেমগুলি অনেক kআইটেম অ্যারে থেকে হয় aএবং এটি এর মান থেকে আহরিত lowএবং highsizeBআমরা একইভাবে সংজ্ঞাটি বাদ দিয়ে মানটি এমনভাবে গণনা করি sizeA+sizeB=k। এই দুটি সীমানার মানগুলির উপর ভিত্তি করে এই সিদ্ধান্তে পৌঁছে যে আমাদের অ্যারেতে ডানদিকে প্রসারিত করতে হবে aবা বাম দিকে সঙ্কুচিত করতে হবে। যদি আমরা একই অবস্থান আটকে এটা মানে যে আমরা সমাধান পাওয়া যায় এবং আমরা অবস্থানে মূল্যবোধের সর্বোচ্চ ফিরে আসবে sizeA-1থেকে aএবং sizeB-1থেকে b


0

এই কোডটি পরীক্ষা করুন।

import math
def findkthsmallest():

    A=[1,5,10,22,30,35,75,125,150,175,200]
    B=[15,16,20,22,25,30,100,155,160,170]
    lM=0
    lN=0
    hM=len(A)-1
    hN=len(B)-1
    k=17

    while True:
        if k==1:
            return min(A[lM],B[lN])


        cM=hM-lM+1
        cN=hN-lN+1
        tmp = cM/float(cM+cN)
        iM=int(math.ceil(tmp*k))
        iN=k-iM
        iM=lM+iM-1
        iN=lN+iN-1
        if A[iM] >= B[iN]:
            if iN == hN or A[iM] < B[iN+1]:
                return A[iM]
            else:
                k = k - (iN-lN+1)
                lN=iN+1
                hM=iM-1
        if B[iN] >= A[iM]:
            if iM == hM or B[iN] < A[iM+1]:
                return B[iN]
            else:
                k = k - (iM-lM+1)
                lM=iM+1
                hN=iN-1
        if hM < lM:
            return B[lN+k-1]
        if hN < lN:
            return A[lM+k-1]

if __name__ == '__main__':
    print findkthsmallest();

ব্যাখ্যা সরবরাহ করুন
অভিজিৎ সরকার ২

0

সি সাজানো কোডের নীচে দুটি সাজানো অ্যারের ইউনিয়নে কে-থতম ক্ষুদ্রতম এলিমেন্টটি সন্ধান করতে। সময় জটিলতা: ও (লগ)

        public static int findKthSmallestElement1(int[] A, int startA, int endA, int[] B, int startB, int endB, int k)
        {
            int n = endA - startA;
            int m = endB - startB;

            if (n <= 0)
                return B[startB + k - 1];
            if (m <= 0)
                return A[startA + k - 1];
            if (k == 1)
                return A[startA] < B[startB] ? A[startA] : B[startB];

            int midA = (startA + endA) / 2;
            int midB = (startB + endB) / 2;

            if (A[midA] <= B[midB])
            {
                if (n / 2 + m / 2 + 1 >= k)
                    return findKthSmallestElement1(A, startA, endA, B, startB, midB, k);
                else
                    return findKthSmallestElement1(A, midA + 1, endA, B, startB, endB, k - n / 2 - 1);
            }
            else
            {
                if (n / 2 + m / 2 + 1 >= k)
                    return findKthSmallestElement1(A, startA, midA, B, startB, endB, k);
                else
                    return findKthSmallestElement1(A, startA, endA, B, midB + 1, endB, k - m / 2 - 1);

            }
        }

কোনও ত্রুটি নেই, এসও
পীযুষ প্যাটেল

1
Sammy333 ধন্যবাদ, আমি কোড আপডেট করেছি। এখন এটির কার্যকরী এক
পীযূষ প্যাটেল

(গনা না midAথেকে endAযদি k < nছোট অ্যারে জন্য পরীক্ষা করে দেখুন, থেকে শুরু। return B[startB + k - 1];।)
বৃদ্ধলোক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.