दिलचस्प पोस्ट
ऊंचा प्रक्रिया चलाएं मैं jQuery के साथ छद्म तत्वों की शैली गुणों का उपयोग कैसे करूं? क्या एक यूनिट टेस्ट प्रोजेक्ट लक्ष्य एप्लिकेशन की ऐप.कॉन्फिग फ़ाइल लोड कर सकता है? उद्देश्य सी का उपयोग करके iPhone फ़ॉइड साइड मेनू चौड़ाई के बिना एक div ब्लॉक को केंद्रित करना कैसे जावा में हिश कोड () की गणना की जाती है एक जावास्क्रिप्ट फ़ंक्शन को प्रोग्राम में जोड़ना डॉक आइकन कैसे छिपाएगा हाइबरनेट में डिफ़ॉल्ट मान कैसे सेट करें सी ++ और जावा में "सामान्य" प्रकार के बीच अंतर क्या हैं? यह जांच कैसे करें कि कोई ऐप iPhone पर किसी वेब पेज से इंस्टॉल है या नहीं? jQuery स्क्रॉल पेज / iframe के नीचे स्क्रॉल करें dplyr पंक्ति परिवर्तन के लिए गणना गणना या कस्टम कार्यों बैकस्पेस कुंजी को वापस नेविगेट करने से मैं कैसे रोक सकता हूं? __builtin_offsetof ऑपरेटर का उद्देश्य और वापसी प्रकार क्या है?

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

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

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

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

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

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

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

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

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

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

स्पष्ट रूप से, यदि हम सभी संभव 3-ट्यूपल्स का परीक्षण करते हैं, तो हम ओ (एन 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 ले जाएं।

प्रत्येक के लिए, j और k के संकेत धीरे-धीरे एक दूसरे के करीब आ जाएंगे। आखिरकार वे एक-दूसरे को पार करेंगे, और उस समय हमें इसके लिए कुछ और करने की ज़रूरत नहीं है, क्योंकि हम उसी तत्व का संक्षेप चाहते हैं, सिर्फ एक अलग क्रम में। उस बिंदु के बाद, हम अगले i कोशिश और दोहराना।

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


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

निश्चित रूप से यह एक बेहतर समाधान है क्योंकि यह पढ़ने के लिए आसान है और इसलिए त्रुटियों को कम प्रवण। एकमात्र समस्या यह है, हमें एक तत्व के एकाधिक चयन से बचने के लिए कुछ पंक्तियाँ कोड जोड़ना होगा।

एक अन्य ओ (एन ^ 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]) 

मेरा मानना ​​है कि हम द्विआधारी खोज का उपयोग करने के लिए जॉन फेमिनाला के उत्कृष्ट उत्तर को संशोधित कर सकते हैं, जिससे ओ (एनएलजेएन) को चलाने के समय को कम किया जा सकता है। कस्टम फ़ंक्शन binary_search (alist, value, low, high) यदि मिलेगा तो सूचकांक का मूल्य देता है, और -10 अगर यह बाईं ओर समाप्त होता है, -20 यदि यह दाईं ओर समाप्त होता है:

 def triplet_sum(alist, total): alist.sort() #modifies the list in place - more efficient than sorted() but not great if we need the list unmodified left, right = 0, len(alist) - 1 while right > left: elem = total - alist[left] - alist[right] mid = binary_search(alist, elem, left, right) if mid >= 0: #found return (alist[left], alist[mid], alist[right]) elif mid == -10: #terminated left right -= 1 elif mid == -20: #terminated right left += 1 return None 
  • सबसे पहले सूची – ओ (एनएलजेएन) का समय
  • बाएं 0 के रूप में शुरू होता है, और ठीक n-1 (अंतिम सूचकांक) के रूप में
  • बाइनरी तीसरे तत्व के लिए खोज जो कुल योग – ओ (लॉगन) समय को पूरा करता है
  • यदि मिल जाए, तो त्रिगुण वापस लौटें
  • यदि द्विआधारी खोज सूची के बाईं ओर समाप्त हो जाती है, तो दायरे में कमी
  • यदि द्विआधारी खोज सही पक्ष में समाप्त हो जाती है, वेतन वृद्धि बाएं

जबकि लूप ओ (एन) बार चलाता है, हर बार हे (लॉगन) काम करता है, ओ के कुल (nlogn) के लिए। मुझे पता है कि यह मदद करता है, और मुझे कोई सुधार / सुझाव सुनना अच्छा लगेगा

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

जॉन फेमिनाला के समाधान में एक बग है

लाइन पर

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

ध्यान दें कि हमारे पास क्रमबद्ध सरणी है यह समाधान जॉन के समाधान के समान है, जो कि वह राशि के लिए दिखता है और उसी तत्व को दोहराता नहीं है।

 #include &lt;stdio.h&gt; int checkForSum (int arr[], int len, int sum) { //arr is sorted int i; for (i = 0; i &lt; len ; i++) { int left = i + 1; int right = len - 1; while (right &gt; 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)); } 

यहां सी ++ कोड है:

 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 * लॉगएन समाधान: इनपुट सरणी को सॉर्ट करें, फिर सभी जोड़े ए I , ए जे (एन ^ 2 टाइम) के माध्यम से जाएं, और प्रत्येक जोड़ी के लिए जांच करें कि (एस – ए i – ए जे ) सरणी में है ( लॉगएन समय)

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

संक्षेप में:

2-डी सरणी वी [4] [एस + 1] बनाएँ इसे इस तरह भरें, कि:

वी [0] [0] = 1, वी [0] [x] = 0;

किसी भी मैं के लिए वी 1 [ए मैं ] = 1, सभी 1 एक्स के लिए वी 1 [x] = 0

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

वी [3] [किसी भी 3 तत्वों का योग] = 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,ie 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; } } 

कमी: मुझे लगता है कि @ जॉन फेमिनाला समाधान ओ (एन 2) सबसे खूबसूरत है। हम अभी भी ए [एन] को कम कर सकते हैं जिसमें ट्यूपल की खोज करना है ए [के] को देखते हुए कि सभी तत्व ए [0] – ए [के] में होंगे, जब हमारी खोज सरणी बहुत बड़ी होती है और एसएम (एस) वास्तव में छोटे होते हैं

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

एस = 2 ए [0] + ए [के]: एस और ए [] को देखते हुए हम लॉग इन (एन) समय में द्विआधारी खोज का उपयोग कर ए [के] पा सकते हैं।

एक अन्य समाधान जो जांचता है और जल्दी विफल रहता है:

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

मैंने यहां कुछ यूनिट परीक्षण जोड़े: GivenArrayReturnTrueIfThreeElementsSumZeroTest ।

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

यहां जावा में प्रोग्राम है जो ओ (एन ^ 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. ie 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); } } 

यह समस्या ओ (एन ^ 2) में मामूली संशोधनों के साथ 2-सममितीय समस्या का विस्तार करके हल की जा सकती है। ए एक तत्व युक्त तत्व है और बी आवश्यक राशि है।

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

 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; 

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

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

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

// यदि arr [i] और arr [j] का योग वांछित योग से कम है तो तीसरे अंक की खोज करने की क्षमता है, ऐसा करने के लिए किसी अन्य पाश

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

// इस मामले में हम अब तीसरे मान की तलाश कर रहे हैं; अगर arr [i] और arr [j] और arr [k] का योग वांछित राशि है तो उन्हें एश [आई] की कुंजी बनाकर और फिर arr [j] और arr [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]);} 

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