একটি অ্যারেতে তিনটি উপাদান সন্ধান করা হচ্ছে যার যোগফল একটি প্রদত্ত সংখ্যার নিকটতম


155

Inte ণাত্মক এবং ধনাত্মক এবং আরও একটি পূর্ণসংখ্যক এস সহ একটি পূর্ণসংখ্যার অ্যারে দেওয়া হয়েছে, A 1 , A 2 , ..., A এন এবং এখন আমাদের অ্যারেতে তিনটি পৃথক পূর্ণসংখ্যার সন্ধান করা দরকার, যার যোগফল প্রদত্ত পূর্ণসংখ্যার S এর নিকটতম। যদি একাধিক সমাধান উপস্থিত থাকে তবে সেগুলির যে কোনও একটি ঠিক আছে।

আপনি অনুমান করতে পারেন যে সমস্ত পূর্ণসংখ্যাগুলি আন্তঃ 32_t সীমার মধ্যে রয়েছে এবং অঙ্কের গণনা করার সাথে কোনও পাটিগণিতের ওভারফ্লো হবে না। এস এলোমেলোভাবে বেছে নেওয়া সংখ্যা ছাড়া বিশেষ কিছু নয়।

তিনটি পূর্ণসংখ্যার সন্ধানের জন্য ব্রুট ফোর্স অনুসন্ধান ব্যতীত অন্য কোনও কার্যকর অ্যালগরিদম কি আছে?


1
যদি আপনি একটি সংখ্যার সমান পরিমাণের সন্ধান করেন (এবং নিকটতম নয়) তবে এটি 3SUM সমস্যা হবে
বার্নহার্ড বার্কার

উত্তর:


186

তিনটি পূর্ণসংখ্যার সন্ধানের জন্য ব্রুট ফোর্স অনুসন্ধান ব্যতীত অন্য কোনও কার্যকর অ্যালগরিদম কি আছে?

হাঁ; আমরা ও (এন 2 ) সময়ে এটি সমাধান করতে পারি ! প্রথমে বিবেচনা করুন যে আপনার সমস্যাটিকে Pকিছুটা আলাদা উপায়ে সমানভাবে চিহ্নিত করা যেতে পারে যা "টার্গেট মান" এর প্রয়োজনীয়তা দূর করে:

মূল সমস্যা P: একটি অ্যারের দেওয়া Aএর nইন্টিজার এবং একটি টার্গেট মান Sসেখান থেকে একটি 3-tuple বিদ্যমান Aযে অঙ্কের S?

পরিবর্তিত সমস্যা P': একটি অ্যারের দেওয়া Aএর nইন্টিজার, নেই থেকে একটি 3-tuple বিদ্যমান Aশূন্য যে অঙ্কের?

লক্ষ্য করুন যে সমস্যার প্রতিটি সংস্করণ P'থেকে Pআপনার এস / 3 বিয়োগ করে সমস্যার এই সংস্করণটি থেকে আপনি যেতে পারেন Aতবে এখন আর আপনার লক্ষ্য মানটির প্রয়োজন নেই।

স্পষ্টতই, আমরা যদি সহজভাবে সমস্ত 3 টি টিপল পরীক্ষা করি তবে আমরা O (n 3 ) এ সমস্যার সমাধান করব - এটি হ'ল ব্রুট ফোর্স বেসলাইন। এটা কি আরও ভাল করা সম্ভব? আমরা যদি কিছুটা স্মার্ট উপায়ে টিপলগুলি বাছাই করি?

প্রথমে আমরা অ্যারে বাছাই করতে কিছুটা সময় ব্যয় করি যা আমাদের ও (n লগ এন) এর প্রাথমিক জরিমানা ব্যয় করে। এখন আমরা এই অ্যালগরিদম কার্যকর করি:

for (i in 1..n-2) {
  j = i+1  // Start right after i.
  k = n    // Start at the end of the array.

  while (k >= j) {
    // We got a match! All done.
    if (A[i] + A[j] + A[k] == 0) return (A[i], A[j], A[k])

    // We didn't match. Let's try to get a little closer:
    //   If the sum was too big, decrement k.
    //   If the sum was too small, increment j.
    (A[i] + A[j] + A[k] > 0) ? k-- : j++
  }
  // When the while-loop finishes, j and k have passed each other and there's
  // no more useful combinations that we can try with this i.
}

এই অ্যালগরিদম স্থাপন তিন পয়েন্টার, করে কাজ করে i, jএবং kঅ্যারের মধ্যে বিভিন্ন বিন্দুতে। iশুরুতে শুরু হয় এবং ধীরে ধীরে শেষের দিকে কাজ করে। kখুব শেষ উপাদান নির্দেশ করে। jযেখানে iশুরু হয়েছে নির্দেশ করে। আমরা পুনরাবৃত্তভাবে তাদের নিজ নিজ সূচকে উপাদানগুলি যোগ করার চেষ্টা করি এবং প্রতিবার নিম্নলিখিতগুলির মধ্যে একটি ঘটে:

  • যোগফল ঠিক ঠিক! আমরা উত্তর খুঁজে পেয়েছি।
  • যোগফল খুব সামান্য ছিল। jপরবর্তী বৃহত্তম নম্বরটি নির্বাচন করতে শেষের কাছাকাছি যান ।
  • যোগফলটি খুব বড় ছিল। kপরবর্তী ক্ষুদ্রতম সংখ্যাটি নির্বাচন করতে শুরুতে আরও এগিয়ে যান ।

প্রতিটি জন্য i, এর পয়েন্টার jএবং kধীরে ধীরে একে অপরের কাছাকাছি যেতে হবে। শেষ পর্যন্ত তারা একে অপরকে পাস করবে এবং সেই মুহুর্তে আমাদের এর জন্য আর কিছু করার দরকার নেই i, যেহেতু আমরা একই উপাদানগুলি সংশ্লেষ করব, কেবল একটি ভিন্ন ক্রমে। এই বিন্দু পরে, আমরা পরবর্তী চেষ্টা iএবং পুনরাবৃত্তি।

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


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


8
দেখে মনে হচ্ছে অ্যালগরিদমটি কেবল এস -এর সমান 3 টি-
টুপল

7
জেলুএক্স: আমি নোটটিতে যেমন উল্লেখ করেছি, ইন্টারভিউয়ের সমস্যা হওয়ায় আমি খুব বেশি দূরে দিতে চাইনি। আশা করি আপনি এটি কীভাবে সংশোধন করবেন তা দেখতে পাবেন যাতে এটি আপনাকে নিকটতম উত্তর পেয়ে যায় though (ইঙ্গিত: একটি উপায় হ'ল নিকটতম উত্তরের উত্তর অবধি ট্র্যাক করা এবং যদি আপনি আরও ভাল উত্তর খুঁজে পান তবে এটি ওভাররাইট করা))
জন ফেমেনিেলা

12
যদি আমরা সমস্যার বিবৃতিটি সংশোধন না করি তবে এর পরিবর্তে আমরা এজে এবং আকের সন্ধান করব যা +++ এর যোগফল।
বুলিয়ান

3
@ জেলুএক্স: এটি একটি মার্জ সাজানোর কাজটি করার মতোই (এটি আমার জন্য প্রথম ক্লিক করা হয়েছিল)। অভ্যন্তরীণ লুপটি যা করার চেষ্টা করছে তা প্রমাণ করে যে [এ] জে বা এ [কে] হয় কোনও সন্তোষজনক সমাধানের অংশ হতে পারে না । যে কোনও মুহুর্তে সমস্যাটি হ'ল: "কোনও জোড় জে>> = জ এবং কে '<= কে কি এ [জে] + এ [কে] = এস - এ [আই] আছে?" বর্তমান জুটির দিকে তাকানো (i, j), সেখানে 3 টি সম্ভাবনা রয়েছে: যোগফল বড় হয় (থামুন - আমরা জিতেছি!), এটি খুব কম, বা এটি খুব বেশি। যদি এটি খুব কম হয় তবে প্রতিটি কে '<= কে জন্য যোগফল [জে] + এ [কে'] অবশ্যই খুব কম হওয়া উচিত , কারণ এই জাতীয় প্রতিটি রাশিতে প্রথম পদটি (এ [জে]) সমান হবে। ..
j_random_hacker

1
... এবং দ্বিতীয় পদটি (এ [কে ']) এ [কে] এর চেয়ে সমান বা এমনকি কম হবে। সুতরাং এক্ষেত্রে আমরা প্রমাণ করেছি যে এ [জে] কোনও সন্তোষজনক পরিমাণে অংশ নিতে পারে না - তাই আমরা এটিকেও ত্যাগ করতে পারি! যা আমরা j = j + 1 সেট করে এবং আবার শুরু করে যা করি (যদিও এর পরিবর্তে এটি একটি ছোট সাবপ্রব্লেমটি পুনরাবৃত্তভাবে সমাধান করার ক্ষেত্রে বিবেচনা করতে সহায়তা করতে পারে)। একইভাবে যদি যোগফল [জে] + এ [কে] খুব বেশি হয়, তবে আমরা জানি যে এ [জে]] + এ [কে] প্রতিটি জে>> = জ এর জন্যও খুব বেশি হওয়া উচিত , যেহেতু এ [জে]] অবশ্যই কমপক্ষে A [j] এর মতো বড় হওয়া উচিত এবং আমরা ইতিমধ্যে খুব বেশি। এর অর্থ আমরা কে [কে] 1 সেট করে এবং আরম্ভ করে নিরাপদে এ [কে] কে বাতিল করতে পারি।
j_random_hacker

28

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

আরেকটি ও (এন ^ 2) সমাধান (হ্যাশসেট ব্যবহার করে)।

// K is the sum that we are looking for
for i 1..n
    int s1 = K - A[i]
    for j 1..i
        int s2 = s1 - A[j]
        if (set.contains(s2))
            print the numbers
    set.add(A[i])

8
ডাউনসাইড হ'ল ও (এন) স্টোরেজ, এটি জায়গায় জায়গায় না করে।
চার্লস মুঙ্গার

6
একটি হ্যাশসেট ব্যবহার করা কঠোর ও (N ^ 2) নয় কারণ হ্যাশ সেট বিরল ইভেন্টগুলিতে হ্রাস পেতে পারে, ফলস্বরূপ রৈখিক অনুসন্ধানের সময় পর্যন্ত অবতীর্ণ হয়।
Ext3h

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

আমি মনে করি আপনার অ্যালগরিদমে একটি ত্রুটি আছে। s2ইতিমধ্যে একটি নির্বাচিত উপাদান হতে পারে। উদাহরণস্বরূপ যদি অ্যারে হয় 0,1,2এবং Kহয় 2তবে কোনও উত্তর দেওয়া উচিত নয়। আমি মনে করি আপনার অ্যালগরিদম আউটপুট দেবে 0,1,1যা স্পষ্টতই ভুল।
ইয়ামচা

7

জন ফেমিনেলার সমাধানটিতে একটি বাগ রয়েছে।

লাইনে

if (A[i] + A[j] + A[k] == 0) return (A[i], A[j], A[k])

আই, জে, কে সব স্বতন্ত্র কিনা তা আমাদের খতিয়ে দেখা দরকার। অন্যথায়, যদি আমার লক্ষ্য উপাদানটি হয় 6এবং যদি আমার ইনপুট অ্যারে থাকে {3,2,1,7,9,0,-4,6}। আমি যদি 6 টির সমষ্টিযুক্ত টিউপগুলি মুদ্রণ করি তবে আমি 0,0,6আউটপুট হিসাবেও পাই । এটি এড়াতে, আমাদের এই অবস্থাটি পরিবর্তন করতে হবে।

if ((A[i] + A[j] + A[k] == 0) && (i!=j) && (i!=k) && (j!=k)) return (A[i], A[j], A[k])

2
জন ফেমিনেলা সমাধান কেবল সমস্যা সমাধানের জন্য অ্যালগরিদম উপস্থাপন করার জন্য, তিনি আরও উল্লেখ করেছেন যে তার সমাধানটি পৃথক সংখ্যা শর্তের জন্য কাজ করবে না এবং আপনাকে কোডের উপরে কিছুটা পরিবর্তন করতে হবে যা তিনি পাঠকের জন্য রেখে গেছেন।
EmptyData

3
প্রকৃতপক্ষে, আমি কখনই জে থাকব না যেহেতু আপনি সর্বদা এটি জে = আই + ১ থেকে শুরু করেন তবে আপনার আসল শর্তটি যা আপনার যাচাই করা উচিত তা হল জে == কে whether যাইহোক, জে <কে-তে যখন লুপটি সেট করে আপনি দীর্ঘ সমস্যা ছাড়াই সমস্যার সমাধান করেছেন, যেহেতু কে সবসময় জে এবং জ এর চেয়ে সবসময় i এর চেয়ে বড় হবে।
লোরেনজোকাস্টিলো

2
এটি প্রশ্নের উত্তরের মতো বলে মনে হচ্ছে না, বরং জন ফেমেনেলার ​​উত্তর সম্পর্কে একটি মন্তব্যের মতো।
বার্নহার্ড বার্কার

6

এটির মতো কী কী, যা ও (এন ^ 2)

for(each ele in the sorted array)
{
    ele = arr[i] - YOUR_NUMBER;
    let front be the pointer to the front of the array;
    let rear be the pointer to the rear element of the array.;

    // till front is not greater than rear.                    
    while(front <= rear)
    {
        if(*front + *rear == ele)
        {
            print "Found triplet "<<*front<<","<<*rear<<","<<ele<<endl;
            break;
        }
        else
        {
            // sum is > ele, so we need to decrease the sum by decrementing rear pointer.
            if((*front + *rear) > ele)
                decrement rear pointer.
            // sum is < ele, so we need to increase the sum by incrementing the front pointer.
            else
                increment front pointer.
        }
    }

এটি আবিষ্কার করে যে 3 টি উপাদানের যোগফল আপনার সংখ্যার সাথে ঠিক সমান। আপনি যদি নিকটতম চান, আপনি এটি ক্ষুদ্রতম ব-দ্বীপ (আপনার বর্তমান ট্রিপলেটের সংখ্যার মধ্যে পার্থক্য) মনে রাখতে এবং সংক্ষিপ্ত আকারে ছোট্ট বদ্বীপের সাথে ত্রিপলিটি মুদ্রণ করতে এটি পরিবর্তন করতে পারেন can


যদি আপনি যোগফল পেতে কে উপাদানগুলি খুঁজতে চান তবে জটিলতাটি কী? আপনি এই মোকাবেলা কিভাবে?
কোডার_15

এই পদ্ধতির সাথে, কে উপাদানসমূহের জটিলতা হ'ল কে (= k (কে-1)) কে> = ২ এর জন্য আপনাকে প্রতিটি অতিরিক্ত সামান্ডের জন্য একটি বাহ্যিক লুপ যুক্ত করতে হবে।
Ext3h

5

মনে রাখবেন যে আমাদের সাজানো অ্যারে রয়েছে। এই দ্রষ্টব্যটি কেবলমাত্র জন এর দ্রবণের অনুরূপ যা এটি যোগফলটি অনুসন্ধান করে এবং একই উপাদানটির পুনরাবৃত্তি করে না।

#include <stdio.h>;

int checkForSum (int arr[], int len, int sum) { //arr is sorted
    int i;
    for (i = 0; i < len ; i++) {
        int left = i + 1;
        int right = len - 1;
        while (right > left) {
            printf ("values are %d %d %d\n", arr[i], arr[left], arr[right]);
            if (arr[right] + arr[left] + arr[i] - sum == 0) {
                printf ("final values are %d %d %d\n", arr[i], arr[left], arr[right]);
                return 1;
            }
            if (arr[right] + arr[left] + arr[i] - sum > 0)
                right--;
            else
                left++;
        }
    }
    return -1;
}
int main (int argc, char **argv) {
    int arr[] = {-99, -45, -6, -5, 0, 9, 12, 16, 21, 29};
    int sum = 4;
    printf ("check for sum %d in arr is %d\n", sum, checkForSum(arr, 10, sum));
}

এর নিখুঁত পার্থক্য গণনা করা প্রয়োজন a[r] + a[l] + a[i] - sum। ব্যবহার করে দেখুন arr = [-1, 2, 1, -4] sum = 1
দিমিত্রি

3

এখানে সি ++ কোডটি রয়েছে:

bool FindSumZero(int a[], int n, int& x, int& y, int& z)
{
    if (n < 3)
        return false;

    sort(a, a+n);

    for (int i = 0; i < n-2; ++i)
    {
        int j = i+1;
        int k = n-1;

        while (k >= j)
        {
            int s = a[i]+a[j]+a[k];

            if (s == 0 && i != j && j != k && k != i)
            {
                x = a[i], y = a[j], z = a[k];
                return true;
            }

            if (s > 0)
                --k;
            else
                ++j;
        }
    }

    return false;
}

2

খুব সাধারণ এন ^ 2 * লগএন সমাধান: ইনপুট অ্যারে বাছাই করুন, তারপরে সমস্ত জোড় A i , A j (N ^ 2 সময়) দিয়ে যান এবং প্রতিটি জোড়ার জন্য (এস - এ আই - এ জে ) অ্যারেতে রয়েছে কিনা তা পরীক্ষা করে দেখুন ( লগএন সময়)।

আর একটি হে (এস * এন) সমাধান ক্লাসিকাল ডায়নামিক প্রোগ্রামিং পদ্ধতির ব্যবহার করে।

সংক্ষেপে:

একটি 2-ডি অ্যারে ভি তৈরি করুন [4] [এস + 1]। এটি এমনভাবে পূরণ করুন যে:

ভি [0] [0] = 1, ভি [0] [এক্স] = 0;

ভি 1 [এ i ] = 1 কোনও আই এর জন্য, ভি 1 [এক্স] = 0 অন্যান্য সমস্ত এক্স এর জন্য

ভি [২] [এ আই + এ জে ] = ১, যে কোনও আই, জেয়ের জন্য। ভি [2] [এক্স] = 0 অন্যান্য সমস্ত এক্স এর জন্য

ভি [3] [যে কোনও 3 টি উপাদানের যোগফল] = 1।

এটি পূরণের জন্য, A i এর মাধ্যমে পুনরাবৃত্তি করুন , প্রতিটি A এর জন্য আমি ডান থেকে বামে অ্যারে দিয়ে পুনরাবৃত্তি করি


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

অ্যারেটি খুব বড় এবং এটি ও (গুলি * এন) নয়। এই পদক্ষেপটি হ'ল (এন ^ 2): ভি [2] [আইআই + অজ] = 1, যে কোনও আই, জে for ভি [2] [এক্স] = 0 অন্যান্য সমস্ত এক্স এর জন্য।
রিচার্ড

1

নিম্নলিখিত হিসাবে ও (এন লগ (এন)) এ দক্ষতার সাথে সমাধান করা যেতে পারে। আমি সমাধান দিচ্ছি যা প্রদত্ত সংখ্যার সমান কোনও তিনটি সংখ্যার যোগফল কিনা তা বলে।

import java.util.*;
public class MainClass {
        public static void main(String[] args) {
        int[] a = {-1, 0, 1, 2, 3, 5, -4, 6};
        System.out.println(((Object) isThreeSumEqualsTarget(a, 11)).toString());
}

public static boolean isThreeSumEqualsTarget(int[] array, int targetNumber) {

    //O(n log (n))
    Arrays.sort(array);
    System.out.println(Arrays.toString(array));

    int leftIndex = 0;
    int rightIndex = array.length - 1;

    //O(n)
    while (leftIndex + 1 < rightIndex - 1) {
        //take sum of two corners
        int sum = array[leftIndex] + array[rightIndex];
        //find if the number matches exactly. Or get the closest match.
        //here i am not storing closest matches. You can do it for yourself.
        //O(log (n)) complexity
        int binarySearchClosestIndex = binarySearch(leftIndex + 1, rightIndex - 1, targetNumber - sum, array);
        //if exact match is found, we already got the answer
        if (-1 == binarySearchClosestIndex) {
            System.out.println(("combo is " + array[leftIndex] + ", " + array[rightIndex] + ", " + (targetNumber - sum)));
            return true;
        }
        //if exact match is not found, we have to decide which pointer, left or right to move inwards
        //we are here means , either we are on left end or on right end
        else {

            //we ended up searching towards start of array,i.e. we need a lesser sum , lets move inwards from right
            //we need to have a lower sum, lets decrease right index
            if (binarySearchClosestIndex == leftIndex + 1) {
                rightIndex--;
            } else if (binarySearchClosestIndex == rightIndex - 1) {
                //we need to have a higher sum, lets decrease right index
                leftIndex++;
            }
        }
    }
    return false;
}

public static int binarySearch(int start, int end, int elem, int[] array) {
    int mid = 0;
    while (start <= end) {
        mid = (start + end) >>> 1;
        if (elem < array[mid]) {
            end = mid - 1;
        } else if (elem > array[mid]) {
            start = mid + 1;
        } else {
            //exact match case
            //Suits more for this particular case to return -1
            return -1;
        }
    }
    return mid;
}
}

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

0

হ্রাস: আমি মনে করি @ জন ফেমিনেলা সমাধান ও (এন 2) সবচেয়ে মার্জিত। টিপল সন্ধানের জন্য আমরা এখনও [এন] হ্রাস করতে পারি। এ [কে] পর্যবেক্ষণ করে যে সমস্ত উপাদান A [0] - এ [কে] এ থাকবে, যখন আমাদের অনুসন্ধানের অ্যারেটি বিশাল এবং এসইএম (গুলি) সত্যিই ছোট হয়।

একটি [0] সর্বনিম্ন: - সাজানো অ্যারে আরোহণ।

s = 2A [0] + এ [কে]: প্রদত্ত এস এবং এ [] আমরা লগ (এন) সময়ে বাইনারি অনুসন্ধান ব্যবহার করে একটি [কে] খুঁজে পেতে পারি।


0

জাভাতে এই প্রোগ্রামটি যা ও (এন ^ 2)

import java.util.Stack;


public class GetTripletPair {

    /** Set a value for target sum */
    public static final int TARGET_SUM = 32;

    private Stack<Integer> stack = new Stack<Integer>();

    /** Store the sum of current elements stored in stack */
    private int sumInStack = 0;
    private int count =0 ;


    public void populateSubset(int[] data, int fromIndex, int endIndex) {

        /*
        * Check if sum of elements stored in Stack is equal to the expected
        * target sum.
        * 
        * If so, call print method to print the candidate satisfied result.
        */
        if (sumInStack == TARGET_SUM) {
            print(stack);
        }

        for (int currentIndex = fromIndex; currentIndex < endIndex; currentIndex++) {

            if (sumInStack + data[currentIndex] <= TARGET_SUM) {
                ++count;
                stack.push(data[currentIndex]);
                sumInStack += data[currentIndex];

                /*
                * Make the currentIndex +1, and then use recursion to proceed
                * further.
                */
                populateSubset(data, currentIndex + 1, endIndex);
                --count;
                sumInStack -= (Integer) stack.pop();
            }else{
            return;
        }
        }
    }

    /**
    * Print satisfied result. i.e. 15 = 4+6+5
    */

    private void print(Stack<Integer> stack) {
        StringBuilder sb = new StringBuilder();
        sb.append(TARGET_SUM).append(" = ");
        for (Integer i : stack) {
            sb.append(i).append("+");
        }
        System.out.println(sb.deleteCharAt(sb.length() - 1).toString());
    }

    private static final int[] DATA = {4,13,14,15,17};

    public static void main(String[] args) {
        GetAllSubsetByStack get = new GetAllSubsetByStack();
        get.populateSubset(DATA, 0, DATA.length);
    }
}

চমৎকার পন্থা, তবে আপনি যে ফলাফলের সংখ্যাটি কোনও ট্রিপলেটে সীমাবদ্ধ করেছেন সেখানে আমি পয়েন্টটি পেতে পারি না। উদাহরণস্বরূপ ইনপুটটি বিবেচনা করুন: [1,11,3,4,5,6,7,8, 2] এবং যোগফল 12, আপনার সমাধান থেকে এটি প্রদর্শিত হচ্ছে [1, 11] [4,8] [1,4, 5,2] ইত্যাদি সমস্ত কাজ করবে।
অনুপম সাইনি

0

অপ্রাপ্তবয়স্ক সংশোধনগুলির সাথে 2-সমষ্টি সমস্যাটি প্রসারিত করে ও (এন ^ 2) এ সমস্যার সমাধান করা যেতে পারে Aএ উপাদানগুলির ভেক্টর এবং বি প্রয়োজনীয় পরিমাণ হয়।

ইন্ট সলিউশন :: থ্রিসুম ক্লসস্ট (ভেক্টর এবং এ, ইনট বি) {

sort(A.begin(),A.end());

int k=0,i,j,closest,val;int diff=INT_MAX;

while(k<A.size()-2)
{
    i=k+1;
    j=A.size()-1;

    while(i<j)
    {
        val=A[i]+A[j]+A[k];
        if(val==B) return B;
        if(abs(B-val)<diff)
        {
            diff=abs(B-val);
            closest=val;
        }
        if(B>val)
        ++i;
        if(B<val) 
        --j;
    }
    ++k;

}
return closest;

0

পাইথন 3 কোডটি এখানে

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        result = set()
        nums.sort()
        L = len(nums)     
        for i in range(L):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            for j in range(i+1,L):
                if j > i + 1 and nums[j] == nums[j-1]:
                    continue  
                l = j+1
                r = L -1
                while l <= r:
                    sum = nums[i] + nums[j] + nums[l]
                    result.add(sum)
                    l = l + 1
                    while l<=r and nums[l] == nums[l-1]:
                        l = l + 1
        result = list(result)
        min = result[0]
        for i in range(1,len(result)):
            if abs(target - result[i]) < abs(target - min):
                min = result[i]
        return min

-1

আর একটি সমাধান যা তাড়াতাড়ি পরীক্ষা করে ব্যর্থ হয়:

public boolean solution(int[] input) {
        int length = input.length;

        if (length < 3) {
            return false;
        }

        // x + y + z = 0  => -z = x + y
        final Set<Integer> z = new HashSet<>(length);
        int zeroCounter = 0, sum; // if they're more than 3 zeros we're done

        for (int element : input) {
            if (element < 0) {
                z.add(element);
            }

            if (element == 0) {
                ++zeroCounter;
                if (zeroCounter >= 3) {
                    return true;
                }
            }
        }

        if (z.isEmpty() || z.size() == length || (z.size() + zeroCounter == length)) {
            return false;
        } else {
            for (int x = 0; x < length; ++x) {
                for (int y = x + 1; y < length; ++y) {
                    sum = input[x] + input[y]; // will use it as inverse addition
                    if (sum < 0) {
                        continue;
                    }
                    if (z.contains(sum * -1)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

আমি এখানে কয়েকটি ইউনিট পরীক্ষা যুক্ত করেছি: গিভেনআরাই রিটার্নট্রু ট্র্যাফিলি এলিমেন্টসুমজিরোস্টেস্ট

যদি সেটটি খুব বেশি জায়গা ব্যবহার করে থাকে তবে আমি খুব সহজেই জাভা.ইটিল.বিটসেট ব্যবহার করতে পারি যা ও (এন / ডাব্লু) স্থান ব্যবহার করবে ।


-1

এই তিনটি উপাদান পেতে প্রোগ্রাম। আমি প্রথমে অ্যারে / তালিকাটি প্রথমে minClosenessসাজিয়েছি এবং সেগুলি প্রতিটি ট্রিপলেটের ভিত্তিতে আপডেট করা হয়েছে ।

public int[] threeSumClosest(ArrayList<Integer> A, int B) {
    Collections.sort(A);
    int ansSum = 0;
    int ans[] = new int[3];
    int minCloseness = Integer.MAX_VALUE;
    for (int i = 0; i < A.size()-2; i++){
        int j = i+1;
        int k = A.size()-1;
        while (j < k){
            int sum = A.get(i) + A.get(j) + A.get(k);
            if (sum < B){
                j++;
            }else{
                k--;
            }
            if (minCloseness >  Math.abs(sum - B)){
                minCloseness = Math.abs(sum - B);
                ans[0] = A.get(i); ans[1] = A.get(j); ans[2] = A.get(k);
            }
        }
    }
    return ans;
}

-2

আমি এটি এন ^ 3 এ করেছি, আমার সিউডোকোড নীচে রয়েছে;

// ইন্টিজার হিসাবে কী এবং অ্যারেলিস্ট হিসাবে মান সহ একটি হ্যাশম্যাপ তৈরি করুন // লুপের জন্য একটি লুপ ব্যবহার করে তালিকার মাধ্যমে পুনরাবৃত্তি করুন, তালিকার প্রতিটি মানের জন্য পুনরায় পুনরুক্তি হবে পরবর্তী মান থেকে শুরু করে;

for (int i=0; i<=arr.length-1 ; i++){
    for (int j=i+1; j<=arr.length-1;j++){

// যদি আরার [i] এবং আরার [j] এর যোগফল পছন্দসই অঙ্কের চেয়ে কম হয় তবে তৃতীয় অঙ্কের সম্ভাবনা রয়েছে তাই লুপের জন্য অন্যটি করুন

      if (arr[i]+arr[j] < sum){
        for (int k= j+1; k<=arr.length-1;k++)

// এই ক্ষেত্রে আমরা এখন তৃতীয় মান খুঁজছি; যদি আরার [i] এবং আরার [জে] এবং আরআর [কে] এর যোগফলটি পছন্দসই যোগফল হয় তবে এআরটিকে [i] কী করে এবং তারপরে আরার [জে] এবং অ্যারে [কে] যুক্ত করে এটি হ্যাশম্যাপে যুক্ত করুন কীটির মান হিসাবে অ্যারেলিস্ট

          if (arr[i]+arr[j]+arr[k] ==  sum){              
              map.put(arr[i],new ArrayList<Integer>());
              map.get(arr[i]).add(arr[j]);
              map.get(arr[i]).add(arr[k]);}

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.