क्या तीन पूर्णांक खोजने के लिए जानवर बल खोज के अलावा कोई कुशल एल्गोरिदम है?
हां; हम इसे 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) होगा। यह भी केवल सटीक उत्तर पाता है, निकटतम उत्तर नहीं, जैसा कि शीर्षक में उल्लेख है। पाठक को एक अभ्यास के रूप में, मैं आपको यह बताऊंगा कि कैसे इसे अलग-अलग तत्वों के साथ काम करना है (लेकिन यह एक बहुत ही सरल परिवर्तन है) और सटीक उत्तर (जो कि एक साधारण परिवर्तन भी है)।