किसी सरणी में तीन तत्व ढूंढना जिसका योग किसी दिए गए संख्या के सबसे करीब है


155

पूर्णांक के एक सरणी को देखते हुए, ए 1 , ए 2 , ..., ए एन , नकारात्मक और सकारात्मक सहित, और एक पूर्णांक एस। अब हमें सरणी में तीन अलग-अलग पूर्णांक खोजने की आवश्यकता है, जिनकी राशि दिए गए पूर्णांक एस के सबसे करीब है। । यदि एक से अधिक समाधान मौजूद हैं, तो उनमें से कोई भी ठीक है।

आप मान सकते हैं कि सभी पूर्णांक int32_t सीमा के भीतर हैं, और योग की गणना के साथ कोई अंकगणितीय अतिप्रवाह नहीं होगा। एस कुछ खास नहीं है लेकिन एक बेतरतीब ढंग से उठाया गया नंबर है।

क्या तीन पूर्णांक खोजने के लिए जानवर बल खोज के अलावा कोई कुशल एल्गोरिदम है?


1
यदि आप एक संख्या (और निकटतम नहीं) के बराबर राशि की तलाश कर रहे हैं, तो यह 3SUM समस्या होगी
बर्नहार्ड बार्कर

जवाबों:


186

क्या तीन पूर्णांक खोजने के लिए जानवर बल खोज के अलावा कोई कुशल एल्गोरिदम है?

हां; हम इसे O (n 2 ) समय में हल कर सकते हैं ! पहले, विचार करें कि आपकी समस्या Pको थोड़े अलग तरीके से समान रूप से प्रतिपादित किया जा सकता है जो "लक्ष्य मान" की आवश्यकता को समाप्त करता है:

मूल समस्या P: पूर्णांक Aकी एक सरणी nऔर एक लक्ष्य मान को देखते हुए S, क्या Aउस रकम से 3-ट्यूपल मौजूद है S?

संशोधित समस्या P': पूर्णांक Aकी एक सरणी को देखते हुए n, क्या Aउस राशि से शून्य तक 3-ट्यूपल मौजूद है?

सूचना है कि आप समस्या के इस संस्करण से जा सकते हैं P'से Pप्रत्येक तत्व से अपने एस / 3 को घटा कर A, लेकिन अब आप लक्ष्य मूल्य और आवश्यकता नहीं है।

स्पष्ट रूप से, यदि हम केवल सभी संभावित 3-ट्यूपल्स का परीक्षण करते हैं, तो हम O (n 3 ) में समस्या का समाधान करेंगे - वह है ब्रूट-बल बेसलाइन। क्या बेहतर करना संभव है? क्या होगा अगर हम कुछ हद तक टुपल्स को उठाते हैं?

पहले, हम सरणी को सॉर्ट करने के लिए कुछ समय का निवेश करते हैं, जिससे हमें ओ (एन लॉग एन) का प्रारंभिक जुर्माना लगता है। अब हम इस एल्गोरिथ्म को निष्पादित करते हैं:

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और दोहराते हैं।

आखिरकार, हम या तो उपयोगी संभावनाओं को समाप्त कर देंगे, या हम इसका समाधान ढूंढ लेंगे। आप देख सकते हैं कि यह O (n 2 ) है क्योंकि हम बाहरी लूप O (n) बार निष्पादित करते हैं और हम आंतरिक लूप O (n) बार निष्पादित करते हैं। यदि आप वास्तव में फैंसी प्राप्त करते हैं, तो प्रत्येक पूर्णांक को थोड़ा वेक्टर के रूप में दर्शाते हुए और एक तेजी से फूरियर रूपांतरण का प्रदर्शन करके, यह उप-द्विघात करना संभव है, लेकिन यह इस उत्तर के दायरे से परे है।


नोट: क्योंकि यह एक साक्षात्कार का प्रश्न है, मैंने यहां थोड़ा धोखा दिया है: यह एल्गोरिथ्म एक ही तत्व के चयन को कई बार अनुमति देता है। यही है, (-1, -1, 2) एक वैध समाधान होगा, जैसा कि (0, 0, 0) होगा। यह भी केवल सटीक उत्तर पाता है, निकटतम उत्तर नहीं, जैसा कि शीर्षक में उल्लेख है। पाठक को एक अभ्यास के रूप में, मैं आपको यह बताऊंगा कि कैसे इसे अलग-अलग तत्वों के साथ काम करना है (लेकिन यह एक बहुत ही सरल परिवर्तन है) और सटीक उत्तर (जो कि एक साधारण परिवर्तन भी है)।


8
ऐसा लगता है एल्गोरिथ्म केवल 3-टपल कि मिल सकता है के बराबर होती है एस करने के लिए, नहीं निकटतम एस के लिए
ZelluX

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

12
क्या होगा यदि हम समस्या कथन को संशोधित नहीं करते हैं, इसके बजाय हम aj और ak के लिए खोज करेंगे ai + S।
बूलियन

3
@ZelluX: यह एक मर्ज प्रकार के काम करने के समान है (यह पहली बार मेरे लिए कैसे क्लिक किया गया)। जो आंतरिक लूप करने की कोशिश कर रहा है वह साबित करता है कि ए [जे] या ए [के] किसी भी संतोषजनक समाधान का हिस्सा नहीं हो सकता है । किसी भी बिंदु पर समस्या यह है: "क्या कोई जोड़ी j '> = j और k' <= k ऐसी है कि A [j] + A [k] = S - A [i]?" वर्तमान जोड़ी (i, j) को देखते हुए, 3 संभावनाएं हैं: राशि पर धमाका है (रोक - हमने जीत लिया है!), यह बहुत कम है, या यह बहुत अधिक है। तो यह बहुत कम है, तो योग एक [जे] ने एक [कश्मीर] भी बहुत कम के लिए किया जाना चाहिए कि हर <= कश्मीर, ऐसे प्रत्येक राशि में के बाद से पहले कार्यकाल (ए [जे]) ही होगा कश्मीर '। ..
j_random_hacker

1
... और दूसरा शब्द (A [k ']) A [k] से समान या उससे भी कम होगा। तो इस मामले में हमने साबित कर दिया है कि ए [जे] किसी भी संतोषजनक राशि में भाग नहीं ले सकता है - इसलिए हम इसे छोड़ सकते हैं! जो हम j = j + 1 सेट करके और शुरू करके करते हैं (हालाँकि इसके बजाय एक छोटे से उपप्रकार को हल करने के मामले में सोचने में मदद मिल सकती है)। इसी तरह यदि A [j] + A [k] बहुत अधिक है, तो हम जानते हैं कि A [j '] + A [k] का प्रत्येक j'> = j के लिए बहुत अधिक होना चाहिए , क्योंकि A [j '] कम से कम ए [जे] के रूप में बड़ा होना चाहिए और हम पहले से ही बहुत ऊंचे हैं। इसका मतलब है कि हम k = k-1 सेट करके और ओवर शुरू करके A [k] को सुरक्षित रूप से त्याग सकते हैं।
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
डाउन-इन स्टोरेज करने के बजाय O (N) स्टोरेज है।
चार्ल्स मुंगेर

6
हैशसेट का उपयोग करना सख्त O (n ^ 2) नहीं है क्योंकि हैश सेट दुर्लभ अवसरों में पतित हो सकता है, जिसके परिणामस्वरूप रेखीय समय तक हो सकता है।
Ext3h

@Charles - जॉन के समाधान के लिए O (N) स्थान की आवश्यकता है, क्योंकि आप छँटाई करते समय मूल सरणी को बदलते हैं। इसका मतलब है कि फ़ंक्शन का उपयोग करने से पहले कॉलर को एक रक्षात्मक प्रतिलिपि की आवश्यकता हो सकती है।
गमलीला

मुझे लगता है कि आपके एल्गोरिथ्म में एक त्रुटि है। 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
जॉन फेमिनाला समाधान समस्या को हल करने के लिए एल्गोरिदम पेश करने के लिए है, उन्होंने यह भी निर्दिष्ट किया है कि उनका समाधान अलग-अलग संख्या की स्थिति के लिए काम नहीं करेगा और आपको कोड को थोड़ा ऊपर संशोधित करना होगा जो उसने पाठक के लिए छोड़ दिया है।
एम्प्टीडाटा

3
दरअसल, मैं कभी भी j नहीं करूंगा क्योंकि आप इसे हमेशा j = i + 1 से शुरू कर रहे हैं। केवल वास्तविक स्थिति जिसे आपको जांचना चाहिए कि क्या j = k है। हालाँकि, जब लूप को j <k पर सेट करके, आपने समस्याओं को बिना लम्बे हल किया है यदि कथन k k हमेशा j और j से अधिक होगा, तो मैं हमेशा से अधिक होता हूँ।
लॉरेंजोकास्टिलो

2
यह सवाल के जवाब की तरह नहीं लगता है, बल्कि जॉन फेमिनेला के जवाब पर एक टिप्पणी की तरह है।
बर्नहार्ड बार्कर

6

कैसे इस तरह के बारे में कुछ है, जो हे (n ^ 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 तत्वों का योग आपकी संख्या के बराबर है। यदि आप निकटतम चाहते हैं, तो आप इसे सबसे छोटे डेल्टा (वर्तमान ट्रिपलेट की संख्या के बीच का अंतर) और अंत में सबसे छोटे डेल्टा से संबंधित ट्रिपल प्रिंट को याद करने के लिए संशोधित कर सकते हैं।


यदि आप राशि प्राप्त करने के लिए k तत्वों को खोजना चाहते हैं तो जटिलता क्या है? आप इससे कैसे निपटेंगे?
कोडर_15

इस दृष्टिकोण के साथ, k तत्वों के लिए जटिलता k> = 2. के लिए O (n ^ (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

यहाँ C ++ कोड है:

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

बहुत सरल N ^ 2 * logN समाधान: इनपुट सरणी को सॉर्ट करें, फिर सभी जोड़े A i , A j (N ^ 2 समय) पर जाएं, और प्रत्येक जोड़ी के लिए जांचें कि क्या (S - A i - A j ) सरणी में है ( logN समय)।

एक और ओ (एस * एन) समाधान शास्त्रीय गतिशील प्रोग्रामिंग दृष्टिकोण का उपयोग करता है ।

संक्षेप में:

एक 2-d सरणी V बनाएँ [4] [S + 1]। इसे इस तरह से भरें, जैसे:

वी [०] [०] = १, वी [०] [एक्स] = ०;

V 1 [A i ] = 1 किसी भी i, V 1 [x] = 0 के लिए अन्य सभी x के लिए

V [2] [A i + A j ] = 1, किसी भी i, j के लिए। V [2] [x] = 0 अन्य सभी x के लिए

V [3] [किसी भी 3 तत्वों का योग] = 1।

इसे भरने के लिए, ए i के माध्यम से पुनरावृति , प्रत्येक ए के लिए मैं दाईं ओर से बाईं ओर सरणी के माध्यम से पुनरावृति करता हूं


पहले एल्गोरिथ्म में थोड़ा परिवर्तन .. यदि तत्व मौजूद नहीं है, तो बाइनरी खोज के अंत में, हमें बाएं, वर्तमान और दाईं ओर के तत्व को देखना होगा, जो निकटतम परिणाम देता है ।
अनुराग

सरणी बहुत बड़ी है और यह O (s * N) नहीं है। यह चरण O (N ^ 2) है: V [2] [ऐ + अज] = 1, किसी भी i, j के लिए। V [2] [x] = 0 अन्य सभी x के लिए।
रिचर्ड

1

इसे निम्नानुसार कुशलतापूर्वक O (n log (n)) में हल किया जा सकता है। मैं समाधान दे रहा हूं जो बताता है कि क्या किसी तीन संख्याओं का योग किसी दिए गए संख्या के बराबर है।

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 [k] को देखने से ऐसा लगता है कि सभी तत्व A [0] - A [k] में होंगे, जब हमारा खोज सरणी बहुत बड़ा है और SUM (s) वास्तव में छोटा है।

एक [0] न्यूनतम है: - आरोही क्रमबद्ध सरणी।

s = 2A [0] + A [k]: दिए गए s और A [] हम लॉग (n) समय में बाइनरी खोज का उपयोग करके A [k] पा सकते हैं।


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

समस्या को O (n ^ 2) में हल किया जा सकता है 2-समस्‍या को मामूली संशोधनों के साथ सम्‍मिलित करके। ए सदिश तत्‍व है और B आवश्‍यक योग है।

इंट सॉल्यूशन :: थ्रीसमक्लोस्ट (वेक्टर और ए, इंट बी) {

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

यहाँ Python3 कोड है

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

मैंने यहां कुछ इकाई परीक्षण जोड़े: गिवारेअरेटर्नट्रेउइफ्रीश्रीजम्ससुमेरोटेस्ट

यदि सेट बहुत अधिक स्थान का उपयोग कर रहा है तो मैं आसानी से एक java.util का उपयोग कर सकता हूं। बिटसेट जो O (n / w) स्थान का उपयोग करेगा ।


-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

मैंने इसे n ^ 3 में किया, मेरा छद्म कोड नीचे है;

// पूर्णांक के रूप में कुंजी के साथ हैश्रैप बनाएं और ArrayList के रूप में मान // एक लूप के लिए सूची के माध्यम से पुनरावृति, सूची में प्रत्येक मान के लिए पुन: अगले मूल्य से शुरू होने वाले पुनरावृति;

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] और गिरफ्तारी [j] और गिरफ्तारी [k] वांछित राशि है, तो इन्हें HashMap को गिरफ्तारी [i] कुंजी बनाकर जोड़ दें और फिर गिरफ्तारी [j] और गिरफ्तारी [k] में जोड़ दें। उस कुंजी के मान में ArrayList

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

इसके बाद अब आपके पास एक ऐसा शब्दकोश है जिसमें सभी प्रविष्टियाँ हैं जो वांछित योग में तीन मानों का प्रतिनिधित्व करती हैं। HashMap कार्यों का उपयोग करके इन सभी प्रविष्टियों को निकालें। यह पूरी तरह से काम किया।

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