आसान साक्षात्कार प्रश्न कठिन हो गया: दिए गए नंबर 1..100, लापता संख्या को ढूंढें जो वास्तव में k गायब हैं


1146

मुझे कुछ समय पहले एक दिलचस्प नौकरी के लिए साक्षात्कार का अनुभव था। प्रश्न वास्तव में आसान शुरू हुआ:

Q1 : हम एक बैग संख्या से युक्त है 1, 2, 3, ..., 100। प्रत्येक संख्या बिल्कुल एक बार दिखाई देती है, इसलिए 100 नंबर हैं। अब एक नंबर बेतरतीब ढंग से बैग से बाहर निकाला जाता है। लापता संख्या का पता लगाएं।

मैंने इस साक्षात्कार प्रश्न को पहले सुना है, निश्चित रूप से, इसलिए मैंने बहुत जल्दी इसका उत्तर दिया:

A1 : ठीक है, संख्याओं 1 + 2 + 3 + … + Nका योग है (N+1)(N/2)(देखें अंकगणितीय श्रृंखला का योग )। के लिए N = 100, योग है 5050

इस प्रकार, यदि सभी नंबर बैग में मौजूद हैं, तो राशि बिल्कुल सही होगी 5050। चूँकि एक संख्या गायब है, योग इस से कम होगा, और अंतर यह है कि संख्या। तो हम उस गुम संख्या को O(N)समय और O(1)स्थान में पा सकते हैं ।

इस बिंदु पर मुझे लगा कि मैंने अच्छा प्रदर्शन किया है, लेकिन अचानक सवाल ने एक अप्रत्याशित मोड़ ले लिया:

Q2 : यह सही है, लेकिन अब अगर दो नंबर गायब हैं तो आप यह कैसे करेंगे ?

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

साक्षात्कारकर्ता ने यह कहकर मुझे प्रोत्साहित करने की कोशिश की कि समस्या का समाधान करने के लिए एक दूसरा समीकरण होना वास्तव में एक तरीका है। इस बिंदु पर मैं परेशान था (हाथ से पहले जवाब नहीं जानने के लिए), और पूछा कि क्या यह एक सामान्य (पढ़ा: "उपयोगी") प्रोग्रामिंग तकनीक है, या यदि यह सिर्फ एक चाल / गोच उत्तर है।

साक्षात्कारकर्ता के जवाब ने मुझे आश्चर्यचकित किया: आप 3 लापता संख्याओं को खोजने के लिए तकनीक को सामान्य कर सकते हैं। वास्तव में, आप इसे k लापता संख्याओं को खोजने के लिए सामान्यीकृत कर सकते हैं ।

Qk : यदि वास्तव में k नंबर बैग से गायब हैं, तो आप इसे कुशलता से कैसे पाएंगे?

यह कुछ महीने पहले था, और मैं अभी भी यह पता नहीं लगा सका कि यह तकनीक क्या है। जाहिर तौर पर एक Ω(N)समय कम है, क्योंकि हमें सभी नंबरों को कम से कम एक बार स्कैन करना होगा, लेकिन साक्षात्कारकर्ता ने जोर देकर कहा कि हल करने की तकनीक ( टाइम इनपुट स्कैन) के टाइम और स्पेस जटिलता को k नहीं NO(N) में परिभाषित किया गया है ।

तो यहाँ सवाल सरल है:

  • आप Q2 को कैसे हल करेंगे ?
  • आप Q3 को कैसे हल करेंगे ?
  • आप Qk को कैसे हल करेंगे ?

स्पष्टीकरण

  • आम तौर पर 1 से एन नंबर होते हैं । एन , न केवल 1..100।
  • मैं स्पष्ट सेट-आधारित समाधान की तलाश में नहीं हूं, उदाहरण के लिए, बिट सेट का उपयोग करके , प्रत्येक नंबर को निर्दिष्ट बिट के मान से उपस्थिति / अनुपस्थिति को एन्कोडिंग करना, इसलिए O(N)अतिरिक्त स्थान में बिट्स का उपयोग करना । हम एन के लिए आनुपातिक कोई अतिरिक्त स्थान नहीं दे सकते ।
  • मैं भी स्पष्ट सॉर्ट-प्रथम दृष्टिकोण की तलाश में नहीं हूं। यह और सेट-आधारित दृष्टिकोण एक साक्षात्कार में ध्यान देने योग्य है (वे लागू करना आसान है, और एन के आधार पर , बहुत व्यावहारिक हो सकता है)। मैं पवित्र कंघी बनानेवाले की रेती समाधान के लिए देख रहा हूँ (जो लागू करने के लिए व्यावहारिक हो सकता है या नहीं भी हो सकता है, लेकिन अभी भी वांछित स्पर्शोन्मुख विशेषताओं है)।

तो फिर, निश्चित रूप से आपको इनपुट को स्कैन करना होगा O(N), लेकिन आप केवल छोटी मात्रा में जानकारी ( k नहीं N के रूप में परिभाषित ) पर कब्जा कर सकते हैं , और उसके बाद k को किसी भी तरह गुम नंबर खोजना होगा ।


7
@polygenel स्नेहक स्पष्टीकरण के लिए धन्यवाद। "मैं एक एल्गोरिथ्म की तलाश कर रहा हूं जो O (N) समय और O (K) स्पेस का उपयोग करता है, जहां K अनुपस्थित संख्याओं की गिनती है"; शुरुआत से स्पष्ट होगा; ;-)
डेव ओ।

7
आपको Q1 के कथन में सटीक होना चाहिए, ताकि आप क्रम में संख्याओं तक नहीं पहुंच सकें। यह शायद आपको स्पष्ट लगता है, लेकिन मैंने कभी भी सवाल और "बैग" शब्द का नहीं सुना (जिसका अर्थ है "मल्टीसेट" के रूप में भी) भ्रमित करने वाला था।
जेरी

7
कृपया निम्नलिखित को पढ़ें क्योंकि यहां दिए गए उत्तर हास्यास्पद हैं: stackoverflow.com/questions/4406110/…

18
जब तक आप एक पूर्णांक वाले O (1) के लिए स्थान की आवश्यकता पर विचार नहीं करते हैं, तब तक संख्याओं के समाधान के लिए लॉग (N) स्थान की आवश्यकता होती है। लेकिन यदि आप अनबाउंड पूर्णांक के लिए अनुमति देते हैं, तो आपके पास केवल एक पूर्णांक के साथ जितना चाहें उतना स्थान होगा।
उडो क्लेन

3
वैसे Q1 के लिए बहुत अच्छा वैकल्पिक समाधान की गणना की जा सकती है XORसे सभी नंबरों के 1लिए nहै, तो दी सरणी में सभी नंबरों के साथ परिणाम xoring। अंत में आपके पास अपना लापता नंबर है। इस समाधान में आपको ओवरफ्लो के रूप में ओवरऑल के बारे में परवाह करने की आवश्यकता नहीं है।
sbeliakov

जवाबों:


590

यहाँ दिमित्री आंद्रेउ के लिंक का सारांश दिया गया है ।

I-th शक्तियों का योग याद रखें, जहां मैं = 1,2, .., k। यह समीकरणों की प्रणाली को हल करने की समस्या को कम करता है

एक 1 + एक 2 + ... + एक कश्मीर = b 1

एक 1 2 + 2 a 2 2 ... + a k 2 = b 2

...

एक 1 कश्मीर + एक 2 कश्मीर + ... + एक कश्मीर कश्मीर = b कश्मीर

न्यूटन की पहचान का उपयोग करते हुए, b i को जानने के कारण गणना करने की अनुमति मिलती है

सी 1 = एक 1 + एक 2 + ... एक कश्मीर

सी 2 = एक 1 एक 2 + एक 1 एक 3 + ... + एक K-1 एक कश्मीर

...

कश्मीर = एक 1 एक 2 ... एक कश्मीर

यदि आप बहुपद (xa 1 ) ... (xa k ) का विस्तार करते हैं , तो गुणांक बिल्कुल c 1 , ..., c k - Viète के सूत्र देखेंगे । चूंकि प्रत्येक बहुपद कारक विशिष्ट रूप से (बहुपद की अंगूठी एक यूक्लिडियन डोमेन है ), इसका मतलब यह है कि मैं विशिष्ट रूप से क्रमबद्धता तक निर्धारित हूं

यह एक प्रमाण को समाप्त करता है कि संख्याओं को पुनर्प्राप्त करने के लिए शक्तियों को याद रखना पर्याप्त है। निरंतर k के लिए, यह एक अच्छा तरीका है।

हालाँकि, जब k अलग-अलग हो रहा है, तो कंप्यूटिंग c 1 , ..., c k का प्रत्यक्ष दृष्टिकोण अत्यधिक महंगा है, क्योंकि उदाहरण के लिए c k सभी लापता नंबरों का उत्पाद है, परिमाण n! / (Nk) !. इसे दूर करने के लिए, Z q फ़ील्ड में संगणनाएँ निष्पादित करें , जहाँ q एक ऐसा प्रधान है कि n <= q <2n - यह बर्ट्रेंड के डाक द्वारा मौजूद है । प्रमाण को बदलने की आवश्यकता नहीं है, क्योंकि सूत्र अभी भी पकड़े हुए हैं, और बहुपद का गुणन अभी भी अद्वितीय है। आपको परिमित क्षेत्रों पर फैक्टराइजेशन के लिए एक एल्गोरिथ्म की भी आवश्यकता है, उदाहरण के लिए बेर्लेकैंप या कैंटर-ज़सेनहौस

निरंतर k के लिए उच्च स्तर का छद्मकोश:

  • दी गई संख्याओं की i-th शक्तियों की गणना करें
  • अज्ञात संख्याओं की i-th शक्तियां प्राप्त करने के लिए घटाव। Sums b i को बुलाओ ।
  • ख से गणना गुणांकों के लिए उपयोग न्यूटन की सर्वसमिकाओं मैं ; उन्हें ग फोन मैं । मूल रूप से, सी 1 = बी 1 ; सी 2 = (सी 1 बी 1 - बी 2 ) / 2; सटीक सूत्रों के लिए विकिपीडिया देखें
  • फैक्टर बहुपद एक्स कश्मीर -c 1 एक्स कश्मीर -1 + ... + ग कश्मीर
  • बहुपद की जड़ों आवश्यक संख्या एक हैं 1 , ..., एक कश्मीर

अलग-अलग कश्मीर के लिए, एक प्रमुख n <= q <2n का उपयोग करें जैसे कि मिलर-राबिन का उपयोग करें, और सभी संख्याओं के साथ चरणों को कम करें modulo q।

EDIT: इस उत्तर के पिछले संस्करण में कहा गया है कि Z q के बजाय , जहाँ q अभाज्य है, विशेषता 2 के परिमित क्षेत्र (q = 2 ^ (log n)) का उपयोग करना संभव है। यह मामला नहीं है, क्योंकि न्यूटन के सूत्र को k से संख्या तक विभाजन की आवश्यकता होती है।


6
आपको एक प्राइम फ़ील्ड का उपयोग करने की आवश्यकता नहीं है, आप भी उपयोग कर सकते हैं q = 2^(log n)। (आपने सुपर कैसे बनाया और सबस्क्राइब किया ?!)
हेनरिक एपफेल्मस

49
+1 यह वास्तव में, वास्तव में चतुर है। उसी समय, यह संदेहास्पद है, कि क्या यह वास्तव में प्रयास के लायक है, या क्या (एक बहुत ही कृत्रिम समस्या का समाधान) इसके दूसरे तरीके से पुन: उपयोग किया जा सकता है। और यहां तक ​​कि अगर यह एक वास्तविक दुनिया की समस्या थी, तो कई प्लेटफार्मों पर सबसे तुच्छ O(N^2)समाधान संभवत: इस सुंदरता को यथोचित रूप से उच्च के लिए बेहतर रूप से बेहतर बना देगा N। मुझे यह सोचने पर मजबूर करता है : smallurl.com/c8fwgw फिर भी, महान काम! मैं सभी गणित के माध्यम से क्रॉल करने का धैर्य नहीं
रखता था

167
मुझे लगता है कि यह एक अद्भुत उत्तर है। मुझे लगता है कि इससे यह भी पता चलता है कि एक साक्षात्कार के खराब होने से एक के बाद एक लापता संख्या का विस्तार कैसे होगा। यहां तक ​​कि पहला एक प्रकार का गोटिया है, लेकिन यह काफी सामान्य है कि यह मूल रूप से दिखाता है "आपने कुछ साक्षात्कार प्रस्तुत किया।" लेकिन एक सीएस प्रमुख से यह जानने के लिए कि k = 1 से परे जाना (विशेष रूप से "एक साक्षात्कार में" मौके पर) थोड़ा मूर्खतापूर्ण है।
corsiKa

5
यह इनपुट पर रीड सोलोमन कोडिंग को प्रभावी ढंग से कर रहा है।
डेविड एहरमन

78
मैं शर्त लगाता हूं कि सूट में सभी नंबर दर्ज करना hash setऔर 1...Nयह देखने के लिए कि क्या गायब हैं, यह निर्धारित करने के लिए लुकअप का उपयोग करते हुए सूट के ऊपर से पुनरावृत्ति करें , यह सबसे सामान्य होगा, kविविधताओं के संबंध में सबसे तेज़ , सबसे डीबग करने योग्य सबसे अधिक टिकाऊ और समझने योग्य समाधान। बेशक गणित का तरीका प्रभावशाली है, लेकिन कहीं न कहीं आपको एक इंजीनियर होने की जरूरत है और गणितज्ञ की नहीं। खासतौर पर जब व्यापार शामिल हो।
v.oddou

243

मुथुकृष्णन के पृष्ठों की एक जोड़ी को पढ़कर आपको यह पता चलेगा - डेटा स्ट्रीम एल्गोरिदम: पहेली 1: गुम नंबर खोजनायह बिल्कुल सामान्यीकरण दिखाता है जिसे आप खोज रहे हैं । संभवतः यह आपके साक्षात्कारकर्ता ने पढ़ा है और उसने इन सवालों को क्यों रखा है।

अब, यदि केवल लोग मुथुकृष्णन के इलाज से उपजी या हटाए गए उत्तरों को हटाना शुरू कर देंगे, और इस पाठ को ढूंढना आसान बना देंगे। :)


इसके अलावा sdcvvc के सीधे संबंधित उत्तर को देखें , जिसमें pseudocode (हुर्रे भी शामिल हैं! उन ट्रिक गणित योगों को पढ़ने की आवश्यकता नहीं है :)) (धन्यवाद, महान काम!)।


ऊह ... यह दिलचस्प है। मुझे मानना ​​पड़ेगा कि मुझे मैथ्स में थोड़ी उलझन हुई, लेकिन मैं इसे स्किम कर रहा था। बाद में देखने के लिए इसे खुला छोड़ सकते हैं। :) और +1 इस लिंक को और अधिक खोजने के लिए। ;-)
क्रिस

2
Google पुस्तकें लिंक मेरे लिए काम नहीं करता है। यहां एक बेहतर संस्करण [पोस्टस्क्रिप्ट फ़ाइल] है।
हेनरिक एपेल्मस

9
वाह। मुझे उम्मीद नहीं की जा सकती थी कि यह उखड़ जाएगा! पिछली बार मैंने समाधान के लिए एक संदर्भ पोस्ट किया था (उस मामले में नूथ) ने खुद को हल करने की कोशिश करने के बजाय, यह वास्तव में नीचा दिखाया गया था: stackoverflow.com/questions/3060104/ ... मेरे अंदर का लाइब्रेरियन आनन्दित हो गया, धन्यवाद :)
दिमित्रिस आंद्रेउ

@Apfelmus, ध्यान दें कि यह एक मसौदा है। (मैं आपको दोष नहीं देता, मैंने किताब खोजने से पहले लगभग एक साल के लिए वास्तविक चीजों के मसौदे को भ्रमित कर दिया)। Btw अगर लिंक काम नहीं करता है, तो आप books.google.com पर जा सकते हैं और "मुथुकृष्णन डेटा स्ट्रीम एल्गोरिदम" (बिना उद्धरण के) खोज सकते हैं , यह सबसे पहले पॉप अप करने के लिए है।
दिमित्री आंद्रेउ

2
कृपया निम्नलिखित को पढ़ें क्योंकि यहाँ दिए गए उत्तर हास्यास्पद हैं: stackoverflow.com/questions/4406110/…

174

हम दोनों संख्याओं और संख्याओं के वर्ग को जोड़कर Q2 को हल कर सकते हैं ।

हम तब समस्या को कम कर सकते हैं

k1 + k2 = x
k1^2 + k2^2 = y

उम्मीद के मूल्यों से नीचे कहाँ xऔर yकितनी दूर हैं।

स्थानापन्न हमें देता है:

(x-k2)^2 + k2^2 = y

तब हम अपनी लापता संख्या निर्धारित करने के लिए हल कर सकते हैं।


7
+1; मैंने चुनिंदा संख्याओं के लिए मेपल में सूत्र की कोशिश की है और यह काम करता है। मैं अभी भी अपने आप को समझा नहीं सकता कि यह क्यों काम करता है, हालांकि।
पॉलीजेन लुब्रिकेंट्स

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

5
समीकरणों की प्रकृति का अर्थ है कि आपको उस समीकरण से k2 के दो मूल्य मिलेंगे। हालाँकि, ते पहले समीकरण से जिसका उपयोग आप k1 उत्पन्न करने के लिए करते हैं, आप देख सकते हैं कि k2 के इन दो मानों का अर्थ होगा कि k1 अन्य मान है इसलिए आपके पास दो समाधान हैं जो समान संख्याएँ हैं, इसके विपरीत तरीका है। यदि आपने abitrently उस k1> k2 को घोषित किया है तो आपके पास द्विघात समीकरण का केवल एक समाधान होगा और इस प्रकार कुल मिलाकर एक समाधान होगा। और प्रश्न की प्रकृति से स्पष्ट रूप से एक उत्तर हमेशा मौजूद होता है इसलिए यह हमेशा काम करता है।
क्रिस

3
किसी दिए गए k1 + k2 के लिए, कई जोड़े हैं। हम इन जोड़ियों को K1 = a + b और K2 = ab के रूप में लिख सकते हैं जहाँ a = (K1 + k2 / 2)। a किसी दी गई राशि के लिए अद्वितीय है। वर्गों का योग (a + b) ** 2 + (ab) ** 2 = 2 * (a 2 + b 2)। किसी दिए गए K1 + K2 के लिए, एक 2 शब्द निश्चित होता है और हम देखते हैं कि b 2 शब्द के कारण वर्गों का योग अद्वितीय होगा । इसलिए, पूर्णांक की एक जोड़ी के लिए मान x और y अद्वितीय हैं।
फकहलर

8
यह कमाल का है। @ user3281743 यहां एक उदाहरण है। लापता संख्याओं (k1 और k2) को 4 और 6. Sum (1 -> 10) = 55 और Sum (1 ^ 2 -> 10 ^ 2) = 385 होने दें। अब x = 55 - (Sum (सभी शेष संख्या) )) और y = 385 - (Sum (सभी शेष संख्याओं के वर्ग)) इस प्रकार x = 10 और y = 52 है। जैसा कि दिखाया गया है कि हमें छोड़ता है: (10 - k2) ^ 2 + k2 ^ 2 = 52 जो आप कर सकते हैं सरल करें: 2k ^ 2 - 20k + 48 = 0. द्विघात समीकरण को हल करने से आपको उत्तर के रूप में 4 और 6 मिलते हैं।
एलेक्सकोरन

137

जैसा कि @j_random_hacker ने बताया, यह O (n) टाइम और O (1) स्पेस में डुप्लिकेट खोजने के समान है , और मेरे जवाब का एक अनुकूलन यहां भी काम करता है।

यह मानते हुए कि "बैग" को 1-आधारित A[]आकार के सरणी द्वारा दर्शाया जाता है N - k, हम O(N)समय में क्यूके को हल कर सकते हैं औरO(k) अतिरिक्त स्थान हैं।

सबसे पहले, हम अपने सरणी A[]को kतत्वों द्वारा विस्तारित करते हैं, ताकि यह अब आकार का हो N। यह O(k)अतिरिक्त जगह है। हम फिर निम्नलिखित छद्म कोड एल्गोरिथ्म चलाते हैं:

for i := n - k + 1 to n
    A[i] := A[1]
end for

for i := 1 to n - k
    while A[A[i]] != A[i] 
        swap(A[i], A[A[i]])
    end while
end for

for i := 1 to n
    if A[i] != i then 
        print i
    end if
end for

पहला लूप kसरणी में पहली प्रविष्टि के रूप में उसी के लिए अतिरिक्त प्रविष्टियों को आरंभीकृत करता है (यह सिर्फ एक सुविधाजनक मूल्य है जिसे हम जानते हैं कि पहले से ही सरणी में मौजूद है - इस चरण के बाद, कोई भी प्रविष्टि जो आकार के प्रारंभिक सरणी में गायब थीN-k कर रहे हैं अभी भी विस्तारित सरणी में गायब है)।

दूसरा लूप विस्तारित सरणी की अनुमति देता है ताकि यदि तत्व xकम से कम एक बार मौजूद हो, तो उन प्रविष्टियों में से एक स्थिति में होA[x]

ध्यान दें कि हालांकि इसमें एक नेस्टेड लूप है, यह अभी भी O(N)समय में चलता है - एक स्वैप केवल तब होता है जब कोई ऐसा होता iहै A[i] != i, और प्रत्येक स्वैप कम से कम एक तत्व सेट करता है A[i] == i, जहां यह पहले सच नहीं था। इसका मतलब है कि स्वैप की कुल संख्या (और इस प्रकार whileलूप बॉडी के निष्पादन की कुल संख्या ) सबसे अधिक है N-1

तीसरा लूप एरे के उन इंडेक्स को प्रिंट करता iहै जो मूल्य द्वारा कब्जा नहीं किए जाते हैं i- इसका मतलब है कि iगायब होना चाहिए।


4
मुझे आश्चर्य है कि इतने कम लोग इस उत्तर को क्यों वोट देते हैं और यहां तक ​​कि इसे एक सही उत्तर के रूप में चिह्नित नहीं किया है। यहाँ पायथन में कोड है। यह O (n) समय में चलता है और अतिरिक्त स्थान O (k) की आवश्यकता होती है। pastebin.com/9jZqnTzV
wall-e

3
@ caf यह बिट्स सेट करने और उन जगहों को गिनने के समान है जहां बिट 0. है और मुझे लगता है कि जब आप एक पूर्णांक सरणी बना रहे हैं तो अधिक मेमोरी व्याप्त है।
फॉक्स

5
"बिट्स सेट करना और उन स्थानों की गिनती करना जहां बिट 0 है" को ओ (एन) अतिरिक्त स्थान की आवश्यकता है, यह समाधान दिखाता है कि ओ (के) अतिरिक्त स्थान का उपयोग कैसे किया जाए।
कैफे डेस

7
इनपुट के रूप में धाराओं के साथ काम नहीं करता है और इनपुट सरणी को संशोधित करता है (हालांकि मुझे यह बहुत पसंद है और विचार उपयोगी है)।
कॉमको

3
@ v.oddou: नहींं, यह ठीक है। स्वैप बदल जाएगा A[i], जिसका अर्थ है कि अगला पुनरावृत्ति पिछले एक के समान दो मूल्यों की तुलना नहीं करेगा। नया A[i]पिछले लूप के समान होगा A[A[i]], लेकिन नया A[A[i]]एक नया मूल्य होगा। यह कोशिश करो और देखो।
कैफे

128

मैंने 4 साल के बच्चे से इस समस्या को हल करने के लिए कहा। उन्होंने संख्याओं को छाँटा और फिर साथ में गिना। इसके लिए O (किचन फ्लोर) की जगह की आवश्यकता होती है, और यह उतना ही आसान काम करता है, जितनी कि कई गेंदें गायब होती हैं।


20
;) आपकी 4 साल की उम्र 5 या / के पास होनी चाहिए और एक प्रतिभाशाली है। मेरी 4 साल की बेटी अभी तक 4 की भी ठीक से गिनती नहीं कर सकती है। अच्छी तरह से निष्पक्ष होने के लिए कहते हैं कि वह अभी मुश्किल से "4" के अस्तित्व को एकीकृत करती है। अन्यथा अब तक वह हमेशा इसे छोड़ देती थी। "1,2,3,5,6,7" उसका सामान्य मतगणना क्रम था। मैंने उसे पेंसिल को एक साथ जोड़ने के लिए कहा और वह फिर से खरोंचने से इनकार करके 1 + 2 = 3 का प्रबंधन करेगा। मैं वास्तव में चिंतित हूं ...: '(meh ..
v.oddou

सरल अभी तक प्रभावी दृष्टिकोण।
पाबोररे

6
O (किचन फ्लोर) haha ​​- लेकिन वह O (n ^ 2) नहीं होगा?

13
O (mgr) मुझे लगता है :)
विक्टर मेलग्रेन

1
@phuclv: उत्तर में कहा गया है कि "इसमें O (रसोई फर्श) की एक अंतरिक्ष आवश्यकता है"। लेकिन किसी भी स्थिति में, यह एक ऐसा उदाहरण है जहां सॉर्टिंग को O (n) समय में प्राप्त किया जा सकता है --- इस चर्चा को देखें ।
एंथोनी लैबर्रे

36

यकीन नहीं, अगर यह सबसे कुशल समाधान है, लेकिन मैं सभी प्रविष्टियों पर लूप करूंगा, और याद रखने के लिए एक बिटसेट का उपयोग करूंगा कि कौन सी संख्याएं निर्धारित हैं, और फिर 0 बिट्स के लिए परीक्षण करें।

मुझे सरल समाधान पसंद हैं - और मैं यह भी मानता हूं, कि यह राशि की गणना या वर्गों आदि के योग से तेज हो सकता है।


11
मैंने इस स्पष्ट उत्तर का प्रस्ताव किया था, लेकिन यह वह नहीं है जो साक्षात्कारकर्ता चाहते थे। मैंने स्पष्ट रूप से प्रश्न में कहा कि यह वह उत्तर नहीं है जिसकी मुझे तलाश है। एक और स्पष्ट जवाब: पहले सॉर्ट करें। न तो O(N)गिनती के प्रकार और न ही O(N log N)तुलना के प्रकार मैं देख रहा हूँ, हालांकि वे दोनों बहुत सरल समाधान हैं।
पॉलीजेनबेलिकेंट

@ पोलियारोपेलेब्रीकेट्स: मैं नहीं कह सकता कि आपने अपने प्रश्न में कहां कहा है। यदि आप बिटसेट को परिणाम मानते हैं, तो कोई दूसरा पास नहीं है। जटिलता है (यदि हम N को स्थिर मानते हैं, जैसा कि साक्षात्कारकर्ता यह कहकर सुझाता है, कि जटिलता " k नहीं N" में परिभाषित है ) O (1), और यदि आपको अधिक "स्वच्छ" परिणाम बनाने की आवश्यकता है, तो आप O (k) प्राप्त करें, जो आपको मिल सकता है सबसे अच्छा है, क्योंकि स्वच्छ परिणाम बनाने के लिए आपको हमेशा O (k) की आवश्यकता होती है।
क्रिस लेचर

"ध्यान दें कि मैं स्पष्ट सेट-आधारित समाधान की तलाश नहीं कर रहा हूं (उदाहरण के लिए एक बिट सेट का उपयोग कर रहा हूं,") मूल प्रश्न से दूसरा अंतिम पैराग्राफ है।
11:16 बजे

9
@ ओम: हाँ, प्रश्न कुछ मिनट पहले संपादित किया गया था। मैं सिर्फ जवाब दे रहा हूं, कि मैं एक साक्षात्कारकर्ता से उम्मीद करूंगा ... कृत्रिम रूप से एक उप-इष्टतम समाधान का निर्माण (आप ओ (एन) + ओ (के) समय को हरा नहीं सकते, कोई फर्क नहीं पड़ता कि आप क्या करते हैं) मेरे लिए कोई मतलब नहीं है - सिवाय इसके कि आप ओ (एन) अतिरिक्त जगह नहीं ले सकते, लेकिन उस पर सवाल स्पष्ट नहीं है।
क्रिस लेचर

3
मैंने प्रश्न को फिर से स्पष्ट करने के लिए संपादित किया है। मैं प्रतिक्रिया / उत्तर की सराहना करता हूं।
पॉलिजेनबेलिकेंट

33

मैंने गणित की जाँच नहीं की है, लेकिन मुझे संदेह है कि Σ(n^2)हम उसी गणना में गणना Σ(n)करते हैं जब हम गणना करते हैं कि दो लापता संख्याएँ प्राप्त करने के लिए पर्याप्त जानकारी प्रदान करें, Σ(n^3)यदि तीन हैं, और इसी तरह।


15

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

हम sdcvvc और दिमित्रिस आंद्रेउ के एल्गोरिदम के समय और स्थान की जटिलता का विश्लेषण कर सकते हैं।

संग्रहण:

l_j = ceil (log_2 (sum_{i=1}^n i^j))
l_j > log_2 n^j  (assuming n >= 0, k >= 0)
l_j > j log_2 n \in \Omega(j log n)

l_j < log_2 ((sum_{i=1}^n i)^j) + 1
l_j < j log_2 (n) + j log_2 (n + 1) - j log_2 (2) + 1
l_j < j log_2 n + j + c \in O(j log n)`

इसलिए l_j \in \Theta(j log n)

उपयोग किए गए कुल संग्रहण: \sum_{j=1}^k l_j \in \Theta(k^2 log n)

अंतरिक्ष का इस्तेमाल किया: मान लिया कि कंप्यूटिंग a^jलेता हैceil(log_2 j) समय, कुल समय:

t = k ceil(\sum_i=1^n log_2 (i)) = k ceil(log_2 (\prod_i=1^n (i)))
t > k log_2 (n^n + O(n^(n-1)))
t > k log_2 (n^n) = kn log_2 (n)  \in \Omega(kn log n)
t < k log_2 (\prod_i=1^n i^i) + 1
t < kn log_2 (n) + 1 \in O(kn log n)

उपयोग किए गए कुल समय: \Theta(kn log n)

यदि यह समय और स्थान संतोषजनक है, तो आप एक सरल पुनरावर्ती एल्गोरिथ्म का उपयोग कर सकते हैं। चलो बी! मैं बैग में ith प्रविष्टि हूं, हटाने से पहले संख्याओं की संख्या, और हटाने की संख्या के कश्मीर। हास्केल सिंटैक्स में ...

let
  -- O(1)
  isInRange low high v = (v >= low) && (v <= high)
  -- O(n - k)
  countInRange low high = sum $ map (fromEnum . isInRange low high . (!)b) [1..(n-k)]
  findMissing l low high krange
    -- O(1) if there is nothing to find.
    | krange=0 = l
    -- O(1) if there is only one possibility.
    | low=high = low:l
    -- Otherwise total of O(knlog(n)) time
    | otherwise =
       let
         mid = (low + high) `div` 2
         klow = countInRange low mid
         khigh = krange - klow
       in
         findMissing (findMissing low mid klow) (mid + 1) high khigh
in
  findMising 1 (n - k) k

भंडारण का उपयोग किया: O(k)सूची के लिए, O(log(n))स्टैक के लिए: O(k + log(n)) यह एल्गोरिथ्म अधिक सहज है, इसमें एक ही समय जटिलता है, और कम जगह का उपयोग करता है।


1
+1, अच्छा लग रहा है लेकिन आपने मुझे स्निपेट # 1 में लाइन 4 से लाइन 5 तक जाने में खो दिया - क्या आप आगे बता सकते हैं? धन्यवाद!
j_random_hacker

isInRangeहै हे (लॉग एन) , नहीं हे (1) : यह, सीमा 1..n में संख्या तुलना तो यह तुलना करने के लिए है हे (लॉग एन) बिट्स। मुझे नहीं पता कि यह त्रुटि बाकी विश्लेषण को किस हद तक प्रभावित करती है।
jcsahnwaldt का कहना है कि GoFundMonica

14

एक मिनट रुकिए। जैसा कि प्रश्न में कहा गया है, बैग में 100 नंबर हैं। कोई फर्क नहीं पड़ता कि कितनी बड़ी k है, इस समस्या को निरंतर समय में हल किया जा सकता है क्योंकि आप एक सेट का उपयोग कर सकते हैं और एक लूप के पुनरावृत्तियों में अधिकतम 100 में सेट से संख्याओं को हटा सकते हैं। 100 स्थिर है। शेष संख्याओं का सेट आपका उत्तर है।

यदि हम 1 से एन तक की संख्या के समाधान को सामान्य करते हैं, तो एन के अलावा कुछ भी नहीं बदलता है, इसलिए हम ओ (एन - के) = ओ (एन) समय में हैं। उदाहरण के लिए, यदि हम बिट सेट का उपयोग करते हैं, तो हम बिट्स को O (N) समय में 1 पर सेट करते हैं, संख्याओं के माध्यम से पुनरावृति करते हैं, बिट्स को 0 पर सेट करते हैं जैसा कि हम जाते हैं (O (Nk) = O (N)) और फिर हम जवाब है।

यह मुझे लगता है कि साक्षात्कारकर्ता आपसे पूछ रहा था कि ओ (एन) समय के बजाय ओ (के) समय में अंतिम सेट की सामग्री को कैसे प्रिंट किया जाए । स्पष्ट रूप से, एक बिट सेट के साथ, आपको यह निर्धारित करने के लिए सभी एन बिट्स के माध्यम से पुनरावृत्त करना होगा कि आपको नंबर प्रिंट करना चाहिए या नहीं। हालाँकि, यदि आप सेट लागू करने के तरीके को बदलते हैं तो आप संख्याओं का k पुनरावृत्तियों में प्रिंट कर सकते हैं। यह एक हैश सेट और दोहरी लिंक की गई सूची में संग्रहीत किए जाने वाले ऑब्जेक्ट में संख्याओं को डालकर किया जाता है। जब आप किसी ऑब्जेक्ट को हैश सेट से हटाते हैं, तो आप उसे सूची से भी हटा देते हैं। उत्तर उस सूची में छोड़ दिए जाएंगे जो अब लंबाई k की है।


9
यह उत्तर बहुत सरल है, और हम सभी जानते हैं कि सरल उत्तर काम नहीं करते हैं! ;) गंभीरता से हालांकि, मूल प्रश्न को संभवतः ओ (के) स्थान की आवश्यकता पर जोर देना चाहिए।
डी.के.

समस्या यह नहीं है कि सरल है लेकिन आपको नक्शे के लिए O (n) अतिरिक्त मेमोरी का उपयोग करना होगा। समस्या का हल मुझे निरंतर समय और निरंतर स्मृति में हल करता है
मोजो रिसीन

3
मुझे यकीन है कि आप साबित कर सकते हैं कि न्यूनतम समाधान कम से कम हे (एन) है। क्योंकि कम है, तो इसका मतलब होगा कि आपने कुछ नंबरों पर भी LOOK नहीं किया है, और चूंकि कोई क्रम निर्दिष्ट नहीं है, इसलिए सभी नंबरों को देखना अनिवार्य है।
v.oddou

यदि हम इनपुट को एक स्ट्रीम के रूप में देखते हैं, और n मेमोरी में रखने के लिए बहुत बड़ा है, तो O (k) मेमोरी की आवश्यकता समझ में आती है। हम अभी भी हैशिंग का उपयोग कर सकते हैं: बस k ^ 2 बाल्टियाँ बनाएं और उनमें से प्रत्येक पर सरल योग एल्गोरिथ्म का उपयोग करें। यह केवल k ^ 2 मेमोरी है और कुछ अधिक बाल्टी का उपयोग सफलता की उच्च संभावना प्राप्त करने के लिए किया जा सकता है।
थॉमस अहले

8

2 (और 3) लापता नंबरों के प्रश्न को हल करने के लिए, आप संशोधित कर सकते हैं quickselect, जो O(n)कि विभाजन में औसतन रन-इन और निरंतर मेमोरी का उपयोग करता है।

  1. विभाजन में एक यादृच्छिक धुरी के संबंध pमें विभाजन l, जिसमें संख्या धुरी से छोटी होती है, और rजिसमें संख्या धुरी से अधिक होती है।

  2. यह निर्धारित करें कि प्रत्येक विभाजन के आकार ( p - 1 - count(l) = count of missing numbers in lऔर n - count(r) - p = count of missing numbers in r) में धुरी मूल्य की तुलना करके 2 लापता संख्याओं का विभाजन

  3. a) यदि प्रत्येक विभाजन एक संख्या याद कर रहा है, तो प्रत्येक गुम संख्या को खोजने के लिए रकम दृष्टिकोण के अंतर का उपयोग करें।

    (1 + 2 + ... + (p-1)) - sum(l) = missing #1 तथा ((p+1) + (p+2) ... + n) - sum(r) = missing #2

    b) यदि एक विभाजन दोनों संख्याओं को याद कर रहा है और विभाजन खाली है, तो लापता संख्याएँ (p-1,p-2)या तो हैं या (p+1,p+2) इस आधार पर कि विभाजन संख्याओं को याद कर रहा है।

    यदि एक विभाजन 2 संख्याओं को याद कर रहा है, लेकिन खाली नहीं है, तो उस भाग पर पुनरावृत्ति करें।

केवल 2 लापता नंबरों के साथ, यह एल्गोरिथ्म हमेशा कम से कम एक विभाजन O(n)को त्यागता है , इसलिए यह क्विकचेक की औसत समय जटिलता को बरकरार रखता है । इसी तरह, 3 गुमशुदा संख्याओं के साथ यह एल्गोरिथ्म प्रत्येक पास के साथ कम से कम एक विभाजन को भी छोड़ देता है (क्योंकि 2 लापता संख्याओं के साथ, केवल 1 विभाजन में कई लापता संख्याएँ होंगी)। हालाँकि, मुझे याद नहीं है कि जब अधिक लापता संख्याएँ जोड़ी जाती हैं तो प्रदर्शन कितना घटता है।

यहां एक कार्यान्वयन है जो इन-प्लेस विभाजन का उपयोग नहीं करता है , इसलिए यह उदाहरण अंतरिक्ष की आवश्यकता को पूरा नहीं करता है, लेकिन यह एल्गोरिथ्म के चरणों का वर्णन करता है:

<?php

  $list = range(1,100);
  unset($list[3]);
  unset($list[31]);

  findMissing($list,1,100);

  function findMissing($list, $min, $max) {
    if(empty($list)) {
      print_r(range($min, $max));
      return;
    }

    $l = $r = [];
    $pivot = array_pop($list);

    foreach($list as $number) {
      if($number < $pivot) {
        $l[] = $number;
      }
      else {
        $r[] = $number;
      }
    }

    if(count($l) == $pivot - $min - 1) {
      // only 1 missing number use difference of sums
      print array_sum(range($min, $pivot-1)) - array_sum($l) . "\n";
    }
    else if(count($l) < $pivot - $min) {
      // more than 1 missing number, recurse
      findMissing($l, $min, $pivot-1);
    }

    if(count($r) == $max - $pivot - 1) {
      // only 1 missing number use difference of sums
      print array_sum(range($pivot + 1, $max)) - array_sum($r) . "\n";
    } else if(count($r) < $max - $pivot) {
      // mroe than 1 missing number recurse
      findMissing($r, $pivot+1, $max);
    }
  }

डेमो


सेट का विभाजन रैखिक स्थान का उपयोग करने जैसा है। कम से कम यह स्ट्रीमिंग सेटिंग में काम नहीं करेगा।
थॉमस अहले

@ThomasAhle en.wikipedia.org/wiki/Selection_algorithm#Space_complexity देखें । जगह में सेट को विभाजित करने के लिए केवल O (1) अतिरिक्त स्थान की आवश्यकता होती है - रैखिक स्थान नहीं। स्ट्रीमिंग सेटिंग में यह O (k) अतिरिक्त स्थान होगा, हालांकि, मूल प्रश्न में स्ट्रीमिंग का उल्लेख नहीं है।
फजट्री

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

1
लेकिन जैसा कि आप कहते हैं, प्रदर्शन में कमी हो सकती है क्योंकि अधिक संख्याएं जोड़ी जाती हैं? हम हमेशा सही कट पाने के लिए लीनियर टाइम मीडियन एल्गोरिथ्म का भी उपयोग कर सकते हैं, लेकिन यदि k नंबर 1, ..., n में अच्छी तरह से फैले हैं, तो आपको प्रून करने से पहले आपको लॉग लेवल "डीप" में जाना होगा। कोई शाखाएं
थॉमस अहले

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

7

यहाँ एक समाधान है जो बिना किसी चतुर चाल के, बिना किसी अतिरिक्त चाल के k बिट्स का उपयोग करता है। निष्पादन समय O (n), अतिरिक्त स्थान O (k)। बस यह साबित करने के लिए कि पहले समाधान पर पढ़ने या एक प्रतिभाशाली होने के बिना इसे हल किया जा सकता है:

void puzzle (int* data, int n, bool* extra, int k)
{
    // data contains n distinct numbers from 1 to n + k, extra provides
    // space for k extra bits. 

    // Rearrange the array so there are (even) even numbers at the start
    // and (odd) odd numbers at the end.
    int even = 0, odd = 0;
    while (even + odd < n)
    {
        if (data [even] % 2 == 0) ++even;
        else if (data [n - 1 - odd] % 2 == 1) ++odd;
        else { int tmp = data [even]; data [even] = data [n - 1 - odd]; 
               data [n - 1 - odd] = tmp; ++even; ++odd; }
    }

    // Erase the lowest bits of all numbers and set the extra bits to 0.
    for (int i = even; i < n; ++i) data [i] -= 1;
    for (int i = 0; i < k; ++i) extra [i] = false;

    // Set a bit for every number that is present
    for (int i = 0; i < n; ++i)
    {
        int tmp = data [i];
        tmp -= (tmp % 2);
        if (i >= even) ++tmp;
        if (tmp <= n) data [tmp - 1] += 1; else extra [tmp - n - 1] = true;
    }

    // Print out the missing ones
    for (int i = 1; i <= n; ++i)
        if (data [i - 1] % 2 == 0) printf ("Number %d is missing\n", i);
    for (int i = n + 1; i <= n + k; ++i)
        if (! extra [i - n - 1]) printf ("Number %d is missing\n", i);

    // Restore the lowest bits again.
    for (int i = 0; i < n; ++i) {
        if (i < even) { if (data [i] % 2 != 0) data [i] -= 1; }
        else { if (data [i] % 2 == 0) data [i] += 1; }
    }
}

क्या आप चाहते थे (data [n - 1 - odd] % 2 == 1) ++odd;?
चार्ल्स

2
क्या आप बता सकते हैं कि यह कैसे काम करता है? मुझे समझ नहीं आ रहा है।
तेयपेम सेप

समाधान बहुत, बहुत सरल होगा, अगर मैं अस्थायी भंडारण के लिए (n + k) बूलियन की एक सरणी का उपयोग कर सकता हूं, लेकिन इसकी अनुमति नहीं है। इसलिए मैं डेटा को पुनर्व्यवस्थित करता हूं, शुरुआत में सम संख्याएँ और सरणी के अंत में विषम संख्याएँ। अब उन n नंबरों के सबसे कम बिट्स का उपयोग अस्थायी भंडारण के लिए किया जा सकता है, क्योंकि मुझे पता है कि कितने सम और विषम नंबर हैं और सबसे कम बिट्स को फिर से संगठित कर सकते हैं! ये n बिट्स और k अतिरिक्त बिट बिल्कुल (n + k) बूलियन हैं जिनकी मुझे आवश्यकता थी।
gnasher729

2
यदि मेमोरी में रखने के लिए डेटा बहुत बड़ा था, तो यह काम नहीं करेगा, और आपने इसे केवल एक स्ट्रीम के रूप में देखा। स्वादिष्ट हैकी हालांकि :)
थॉमस अहले

अंतरिक्ष की जटिलता ओ (1) हो सकती है। पहले पास में, आप सभी संख्याओं को संसाधित करते हैं <(n - k), इस एल्गोरिथ्म द्वारा 'अतिरिक्त' का उपयोग किए बिना। एक दूसरे पास में, आप समता बिट्स को फिर से साफ़ करते हैं और संख्याओं (nk) .. (n) के लिए पहले k पदों का उपयोग करते हैं।
एमु

5

क्या आप जांच सकते हैं कि क्या हर नंबर मौजूद है? यदि हाँ, तो आप यह कोशिश कर सकते हैं:

S = बैग में सभी संख्याओं का योग (S <5050)
Z = लापता संख्याओं का योग 5050 - S

यदि लापता संख्याएँ हैं xऔर yफिर:

x = Z - y और
अधिकतम (x) = Z - 1

तो तुम से सीमा की जांच 1करने के लिए max(x)और नंबर मिल


1
क्या max(x)मतलब है, xएक संख्या कब है?
थॉमस अहले

2
वह संभवतः संख्याओं के समूह से अधिकतम का मतलब है
JavaHopper

यदि हमारे पास 2 से अधिक संख्याएँ हैं, तो इस समाधान का भंडाफोड़ किया जाएगा
ozgeneral

4

हो सकता है यह एल्गोरिथ्म सवाल 1 के लिए काम कर सकता है:

  1. पहले 100 पूर्णांक के पूर्ववर्ती xor (val = 1 ^ 2 ^ 3 ^ 4 .... 100)
  2. तत्वों को xor करें क्योंकि वे इनपुट स्ट्रीम से आते रहते हैं (val1 = val1 ^ next_input)
  3. अंतिम जवाब = val ^ val1

या इससे भी बेहतर:

def GetValue(A)
  val=0
  for i=1 to 100
    do
      val=val^i
    done
  for value in A:
    do
      val=val^value 
    done
  return val

यह एल्गोरिथ्म वास्तव में दो लापता संख्याओं के लिए विस्तारित किया जा सकता है। पहला कदम वही रहता है। जब हम GetValue को दो गुम नंबरों के साथ कॉल करते हैं, तो परिणाम a1^a2दो लापता संख्याएँ होती हैं। हम कहते हैं

val = a1^a2

अब वैल से a1 और a2 को बाहर निकालने के लिए हम वैल में कोई सेट बिट लेते हैं। आइए कहते हैं कि ithबिट को वैल में सेट किया गया है। इसका मतलब है कि ए 1 और ए 2 में अलग-अलग ithस्थिति है। अब हम मूल सरणी पर एक और पुनरावृत्ति करते हैं और दो xor मान रखते हैं। उन संख्याओं में से एक जिनके पास ith बिट सेट है और अन्य जिनके पास ith बिट सेट नहीं है। अब हमारे पास दो बाल्टी नंबर हैं, और इसके गुरुंटेड जो a1 and a2अलग-अलग बाल्टी में झूठ होंगे। अब वही दोहराएं जो हमने बाल्टी के प्रत्येक पर एक लापता तत्व खोजने के लिए किया था।


यह केवल के लिए समस्या हल करती है k=1, है ना? लेकिन मैं xorरकम पर उपयोग करना पसंद करता हूं , यह थोड़ा तेज लगता है।
थॉमस अहले

@ थोमसअहले हां। मैंने अपने उत्तर में उसे बाहर बुलाया है।
bashrc

सही। क्या आपको अंदाजा है कि k = 2 के लिए "दूसरा ऑर्डर" क्या हो सकता है? राशि के लिए चौकों का उपयोग करने के समान, क्या हम एक्सोर के लिए "वर्ग" कर सकते हैं?
थॉमस अहले

1
@ThomasAhle ने 2 लापता नंबरों के लिए काम करने के लिए इसे संशोधित किया।
bashrc

यह मेरा पसंदीदा तरीका है :)
रोबर्ट राजा

3

यदि आपके पास दोनों सूचियों और दोनों सूचियों के उत्पाद का योग है, तो आप Q2 को हल कर सकते हैं।

(l1 मूल है, l2 संशोधित सूची है)

d = sum(l1) - sum(l2)
m = mul(l1) / mul(l2)

हम इसे अनुकूलित कर सकते हैं क्योंकि अंकगणितीय श्रृंखला का योग पहले और अंतिम शब्दों के औसत से कई गुना अधिक है:

n = len(l1)
d = (n/2)*(n+1) - sum(l2)

अब हम जानते हैं कि (यदि ए और बी हटाए गए नंबर हैं):

a + b = d
a * b = m

तो हम इसे पुनर्व्यवस्थित कर सकते हैं:

a = s - b
b * (s - b) = m

और बाहर गुणा करें:

-b^2 + s*b = m

और पुनर्व्यवस्थित करें ताकि दाईं ओर शून्य हो:

-b^2 + s*b - m = 0

तब हम द्विघात सूत्र के साथ हल कर सकते हैं:

b = (-s + sqrt(s^2 - (4*-1*-m)))/-2
a = s - b

नमूना पायथन 3 कोड:

from functools import reduce
import operator
import math
x = list(range(1,21))
sx = (len(x)/2)*(len(x)+1)
x.remove(15)
x.remove(5)
mul = lambda l: reduce(operator.mul,l)
s = sx - sum(x)
m = mul(range(1,21)) / mul(x)
b = (-s + math.sqrt(s**2 - (-4*(-m))))/-2
a = s - b
print(a,b) #15,5

मैं sqrt की जटिलता को नहीं जानता, कम करना और योग करना इसलिए मैं इस समाधान की जटिलता को काम नहीं कर सकता (यदि किसी को पता है तो कृपया नीचे टिप्पणी करें।)


गणना करने के लिए कितना समय और मेमोरी का उपयोग करता है x1*x2*x3*...?
थॉमस अहले

@ThomasAhle यह सूची की लंबाई पर O (n) -टाइम और O (1) -स्पेस है, लेकिन वास्तव में यह गुणन के रूप में अधिक है (कम से कम पायथन में) O (n ^ 1.6)-समय की लंबाई पर संख्या और संख्याएँ O (लॉग एन) हैं जो उनकी लंबाई पर हैं।
तूमास लाककोनेन

@ThomasAhle नहीं, लॉग (a ^ n) = n * log (a) तो आपके पास नंबर को स्टोर करने के लिए O (l लॉग k) -स्पेस होगा। तो लंबाई l और लंबाई k की मूल संख्याओं की सूची को देखते हुए, आपके पास O (l) -स्पेस होगा, लेकिन स्थिर कारक (लॉग k) उन सभी को लिखने से कम होगा। (मुझे नहीं लगता कि मेरी विधि इस सवाल का जवाब देने का एक अच्छा तरीका है।)
तूओमास लाककोनेंन

3

Q2 के लिए यह एक समाधान है जो दूसरों की तुलना में थोड़ा अधिक अक्षम है, लेकिन अभी भी O (N) रनटाइम है और O (k) स्थान लेता है।

मूल एल्गोरिदम को दो बार चलाने का विचार है। पहले एक में आपको कुल संख्या मिलती है जो गायब है, जो आपको लापता संख्याओं की एक ऊपरी सीमा देता है। इस नंबर पर कॉल करते हैं N। आप जानते हैं कि लापता दो संख्याओं का योग होने वाला है N, इसलिए पहला नंबर केवल अंतराल में हो सकता है [1, floor((N-1)/2)]जबकि दूसरा अंदर आने वाला है [floor(N/2)+1,N-1]

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

मुझे लगता है कि इस पद्धति को सामान्यीकृत किया जा सकता है और शायद इनपुट पर एक ही पास के दौरान कई खोज "समानांतर" में चलती हैं, लेकिन मुझे अभी तक पता नहीं चला है कि कैसे।


आहा हाँ यह वही समाधान है जो मैं Q2 के लिए आया था, बस गणना के साथ फिर से एन / 2 से नीचे के सभी नंबरों के लिए नेगेटिव ले रहा था , लेकिन यह और भी बेहतर है!
14 दिसंबर को xjcl

2

मुझे लगता है कि यह किसी भी जटिल गणितीय समीकरणों और सिद्धांतों के बिना किया जा सकता है। नीचे एक जगह और ओ (2 एन) समय जटिलता समाधान के लिए एक प्रस्ताव है:

इनपुट फॉर्म मान्यताओं:

# बैग में संख्या = एन

# लापता संख्याओं के = के

बैग में संख्याओं को लंबाई n की एक सरणी द्वारा दर्शाया गया है

एल्गो = एन के लिए इनपुट सरणी की लंबाई

सरणी में गुम प्रविष्टियाँ (बैग से निकाली गई संख्या) को सरणी में पहले तत्व के मान से बदल दिया जाता है।

उदाहरण के लिए। शुरू में बैग [2,9,3,7,8,6,4,5,1,10] जैसा दिखता है। यदि 4 को निकाल लिया जाता है, तो 4 का मान 2 हो जाएगा (सरणी का पहला तत्व)। इसलिए 4 में से बैग निकालने के बाद ऐसा लगेगा [2,9,3,7,8,6,2,5,5,1,10]

इस समाधान की कुंजी यह है कि INDEX उस मान को मानकर किसी विज़िट की गई संख्या के INDEX को टैग कर सकता है क्योंकि सरणी ट्रेस की गई है।

    IEnumerable<int> GetMissingNumbers(int[] arrayOfNumbers)
    {
        List<int> missingNumbers = new List<int>();
        int arrayLength = arrayOfNumbers.Length;

        //First Pass
        for (int i = 0; i < arrayLength; i++)
        {
            int index = Math.Abs(arrayOfNumbers[i]) - 1;
            if (index > -1)
            {
                arrayOfNumbers[index] = Math.Abs(arrayOfNumbers[index]) * -1; //Marking the visited indexes
            }
        }

        //Second Pass to get missing numbers
        for (int i = 0; i < arrayLength; i++)
        {                
            //If this index is unvisited, means this is a missing number
            if (arrayOfNumbers[i] > 0)
            {
                missingNumbers.Add(i + 1);
            }
        }

        return missingNumbers;
    }

यह बहुत अधिक मेमोरी का उपयोग करता है।
थॉमस अहले

2

स्ट्रीमिंग एल्गोरिदम को इस तरह से सामान्य करने का एक सामान्य तरीका है। यह विचार kस्वतंत्र रूप से उप समस्याओं में तत्वों को 'फैलाने' के लिए यादृच्छिककरण के एक बिट का उपयोग करने के लिए है, जहां हमारा मूल एल्गोरिथ्म हमारे लिए समस्या का हल करता है। इस तकनीक का उपयोग अन्य चीजों के अलावा विरल सिग्नल पुनर्निर्माण में किया जाता है।

यदि सभी गुम नंबरों को अलग-अलग बाल्टियों में रखा गया है, तो सरणी के गैर-शून्य तत्वों में अब लापता संख्याएँ होंगी।

एक विशेष जोड़ी को एक ही बाल्टी में भेजे जाने की संभावना, 1/uसार्वभौमिक हैश फ़ंक्शन की परिभाषा से कम है । चूंकि k^2/2जोड़े के बारे में हैं, इसलिए हमारे पास यह है कि त्रुटि की संभावना सबसे अधिक है k^2/2/u=1/2। यही है, हम कम से कम 50% संभावना के साथ सफल होते हैं, और अगर हम बढ़ जाते हैंu अपनी संभावना बढ़ाते हैं।

ध्यान दें कि यह एल्गोरिथ्म k^2 lognअंतरिक्ष के बिट्स लेता है (हमें lognबिट प्रति सरणी बकेट की आवश्यकता है।) यह @Dimitris आंद्रेउ के उत्तर (विशेष रूप से बहुपद फैक्टराइजेशन की अंतरिक्ष की आवश्यकता, जो यादृच्छिक रूप से भी होता है।) द्वारा आवश्यक स्थान से मेल खाता है। "एल्गोरिथ्म भी निरंतर है। समय के बजाय प्रति अपडेट समयk शक्ति-रकम के मामले में ।

वास्तव में, हम टिप्पणियों में वर्णित चाल का उपयोग करके पावर योग विधि से भी अधिक कुशल हो सकते हैं।


नोट: हम xorप्रत्येक बकेट में भी उपयोग कर सकते हैं , बजाय इसके sumकि हमारी मशीन पर तेज़ हो।
थॉमस अहले

दिलचस्प है, लेकिन मुझे लगता है कि यह केवल अंतरिक्ष की कमी का सम्मान करता है k <= sqrt(n)- कम से कम अगर u=k^2? मान लीजिए कि k = 11 और n = 100 है, तो आपके पास 121 बाल्टियाँ होंगी और एल्गोरिथ्म 100 बिट्स की एक सरणी होने के समान होगा, जिसे आप स्ट्रीम से प्रत्येक # पढ़ने के दौरान चेक करते हैं। बढ़ने uसे सफलता की संभावना बढ़ जाती है, लेकिन अंतरिक्ष बाधा से अधिक होने से पहले आप इसे बढ़ा सकते हैं।
फजीट्री

1
समस्या यह है कि मुझे लगता है की nतुलना में सबसे अधिक समझ में आता kहै, लेकिन आप वास्तव में k lognवर्णित हैशिंग के समान एक विधि के साथ वास्तव में स्थान प्राप्त कर सकते हैं , जबकि अभी भी लगातार समय अद्यतन कर रहे हैं। इसे gnunet.org/eppstein-set-reconciliation में वर्णित किया गया है , शक्तियों के योग की तरह, लेकिन मूल रूप से आपके पास हैश की तरह मजबूत हैश फ़ंक्शन के साथ 'k के दो' हैशट है , जो गारंटी देता है कि कुछ बाल्टी में केवल एक तत्व होगा । डिकोड करने के लिए, आप उस बाल्टी को पहचानते हैं और उसके दोनों बाल्टी से तत्व को निकालते हैं, जो (संभावना) एक और बाल्टी को मुक्त करता है
थॉमस अहले

2

Q2 के लिए एक बहुत ही सरल समाधान जो मुझे आश्चर्य है कि किसी ने पहले से ही उत्तर नहीं दिया है। दो लापता संख्याओं का योग खोजने के लिए Q1 से विधि का उपयोग करें। एस द्वारा इसे निरूपित करते हैं, फिर लापता संख्याओं में से एक S / 2 से छोटा है और दूसरा S / 2 (duh) से बड़ा है। 1 से एस / 2 तक सभी संख्याओं को जोड़ो और लापता संख्याओं के बीच निम्न को खोजने के लिए इसकी तुलना सूत्र के परिणाम (Q1 में विधि के समान) से करें। बड़ा लापता संख्या ज्ञात करने के लिए इसे S से घटाएं।


मुझे लगता है कि यह Svalorzen के उत्तर के समान है , लेकिन आपने इसे बेहतर शब्दों में समझाया। क्या कोई विचार है कि इसे Qk में कैसे सामान्य किया जाए?
जॉन मैकक्लेन

दूसरे उत्तर को याद करने के लिए क्षमा करें। मुझे यकीन नहीं है कि यह $ Q_k $ के लिए सामान्यीकृत करना संभव है क्योंकि उस मामले में आप कुछ सीमा तक सबसे छोटे लापता तत्व को बाध्य नहीं कर सकते। आप जानते हैं कि कुछ तत्व $ S / k $ से छोटे होने चाहिए, लेकिन यह कई तत्वों के लिए सही हो सकता है
Gilad Deutsch

1

बहुत अच्छी समस्या है। मैं Qk के लिए एक सेट अंतर का उपयोग करने के लिए जाऊँगा। बहुत सारी प्रोग्रामिंग भाषाओं में भी इसके लिए समर्थन है, जैसे रूबी में:

missing = (1..100).to_a - bag

यह शायद सबसे कुशल समाधान नहीं है, लेकिन यह एक है जिसका मैं वास्तविक जीवन में उपयोग करूंगा यदि मुझे इस मामले में इस तरह के कार्य (ज्ञात सीमाओं, कम सीमाओं) का सामना करना पड़ा। यदि संख्या का सेट बहुत बड़ा होगा तो मैं एक अधिक कुशल एल्गोरिदम पर विचार करूंगा, लेकिन तब तक सरल समाधान मेरे लिए पर्याप्त होगा।


1
यह बहुत अधिक स्थान का उपयोग करता है।
थॉमस अहले

@ThomasAhle: आप हर दूसरे उत्तर में बेकार टिप्पणियों को क्यों जोड़ रहे हैं? बहुत अधिक स्थान का उपयोग करने के साथ आपका क्या मतलब है?
DarkDust

क्योंकि सवाल कहता है कि "हम एन के लिए आनुपातिक कोई अतिरिक्त स्थान नहीं दे सकते।" यह समाधान ठीक यही करता है।
थॉमस अहले

1

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


गिनती खिलने वाला फिल्टर भी है, जो विलोपन की अनुमति देता है। फिर आप बस सभी नंबरों को जोड़ सकते हैं और जिन्हें आप स्ट्रीम में देखते हैं उन्हें हटा सकते हैं।
थॉमस अहले

Haha यह शायद अधिक व्यावहारिक उत्तरों में से एक है, लेकिन थोड़ा ध्यान दिया जाता है।
1948

1

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

उदाहरण के लिए, यह हो सकता है कि साक्षात्कारकर्ता nसंदेशों को भेजने वाला हो और उसे जानना आवश्यक होk यह जानने की जरूरत है कि उत्तर में परिणाम नहीं हुआ और इसे कम से कम दीवार घड़ी के समय में जानने की जरूरत हैn-k वें उत्तर आने के । मान लें कि संदेश चैनल की प्रकृति ऐसी है कि यहां तक ​​कि पूर्ण बोर में चल रहा है, संदेशों के बीच कुछ प्रसंस्करण करने के लिए पर्याप्त समय है और अंतिम उत्तर आने के बाद अंतिम परिणाम का उत्पादन करने में कितना समय लगता है, इस पर कोई प्रभाव नहीं पड़ता है। उस समय को प्रत्येक भेजे गए संदेश के कुछ पहचानने वाले पहलू को एक सेट में डालने के लिए इस्तेमाल किया जा सकता है और प्रत्येक संगत उत्तर के रूप में इसे हटा दिया जा सकता है। एक बार अंतिम उत्तर आने के बाद, केवल एक ही बात की जानी चाहिए कि सेट से उसके पहचानकर्ता को हटा दिया जाए, जो कि विशिष्ट कार्यान्वयन में होता हैO(log k+1)। उसके बाद, सेट में kलापता तत्वों की सूची है और इसके लिए कोई अतिरिक्त प्रसंस्करण नहीं है।

यह निश्चित रूप से संख्याओं के पूर्व-निर्मित बैग के बैच प्रसंस्करण के लिए सबसे तेज़ दृष्टिकोण नहीं है क्योंकि पूरी बात चलती है O((log 1 + log 2 + ... + log n) + (log n + log n-1 + ... + log k))। लेकिन यह किसी भी मूल्य के लिए काम करता है k(भले ही यह समय से पहले नहीं जाना जाता है) और इसके बाद के संस्करण में इसे इस तरह से लागू किया गया था जो सबसे महत्वपूर्ण अंतराल को कम करता है।


यदि आपके पास केवल O (k ^ 2) अतिरिक्त मेमोरी है तो क्या यह काम करेगा?
थॉमस अहले

1

आप समरूपता (समूहों, गणित भाषा में) के संदर्भ में इसके बारे में सोचकर समाधान को प्रेरित कर सकते हैं। संख्याओं के सेट का क्रम चाहे कोई भी हो, उत्तर समान होना चाहिए। यदि आप kलापता तत्वों को निर्धारित करने में मदद करने के लिए फ़ंक्शंस का उपयोग करने जा रहे हैं, तो आपको इस बारे में सोचना चाहिए कि फ़ंक्शंस के पास क्या गुण हैं: सममित। फ़ंक्शन s_1(x) = x_1 + x_2 + ... + x_nएक सममित फ़ंक्शन का एक उदाहरण है, लेकिन उच्च डिग्री के अन्य हैं। विशेष रूप से, प्राथमिक सममित कार्यों पर विचार करें । डिग्री 2 का प्राथमिक सममित कार्य s_2(x) = x_1 x_2 + x_1 x_3 + ... + x_1 x_n + x_2 x_3 + ... + x_(n-1) x_n, दो तत्वों के सभी उत्पादों का योग है। इसी तरह डिग्री 3 और उच्चतर के प्राथमिक सममित कार्यों के लिए। वे स्पष्ट रूप से सममित हैं। इसके अलावा, यह पता चला है कि वे सभी सममित कार्यों के लिए बिल्डिंग ब्लॉक हैं।

आप प्राथमिक सममितीय कार्यों का निर्माण कर सकते हैं जैसा कि आप उस पर ध्यान देते हैं s_2(x,x_(n+1)) = s_2(x) + s_1(x)(x_(n+1))। आगे के विचार से आपको s_3(x,x_(n+1)) = s_3(x) + s_2(x)(x_(n+1))और भी बहुत कुछ समझाना चाहिए , इसलिए उन्हें एक पास में गणना की जा सकती है।

हम यह कैसे बता सकते हैं कि कौन से आइटम सरणी से गायब थे? बहुपद के बारे में सोचें (z-x_1)(z-x_2)...(z-x_n)0यदि आप किसी भी संख्या में रखते हैं तो यह मूल्यांकन करता है x_i। बहुपद का विस्तार, आपको मिलता है z^n-s_1(x)z^(n-1)+ ... + (-1)^n s_n। प्राथमिक सममित कार्य यहां भी दिखाई देते हैं, जो वास्तव में कोई आश्चर्य की बात नहीं है, क्योंकि बहुपद को एक ही रहना चाहिए यदि हम जड़ों में किसी भी क्रमपरिवर्तन को लागू करते हैं।

इसलिए हम बहुपद का निर्माण कर सकते हैं और यह पता लगाने की कोशिश कर सकते हैं कि कौन सी संख्या सेट में नहीं हैं, जैसा कि दूसरों ने उल्लेख किया है।

अंत में, अगर हम बड़ी संख्या के साथ मेमोरी को ओवरफ्लो करने के बारे में चिंतित हैं (n n n सममित बहुपद क्रम का होगा 100!), तो हम इन गणनाओं को कर सकते हैं mod pजहां p100 से अधिक बड़ा है। उस मामले में हम बहुपद का मूल्यांकन करते हैं mod pऔर पाते हैं कि यह फिर से मूल्यांकन करता है। करने के लिए 0जब इनपुट सेट में एक संख्या है, और यह एक गैर शून्य मान का मूल्यांकन जब इनपुट एक नंबर सेट में नहीं है। हालांकि, जैसा कि दूसरों ने इंगित किया है, समय में बहुपद के मूल्यों को प्राप्त करने के लिए जो निर्भर करता है k, नहीं N, हमें बहुपद का कारक होना चाहिए mod p


1

फिर भी एक और तरीका अवशिष्ट ग्राफ़ फ़िल्टरिंग का उपयोग कर रहा है।

मान लीजिए कि हमारे पास नंबर 1 से 4 है और 3 गायब है। बाइनरी प्रतिनिधित्व निम्नलिखित है,

1 = 001 बी, 2 = 010 बी, 3 = 011 बी, 4 = 100 बी

और मैं निम्न की तरह एक प्रवाह-ग्राफ बना सकता हूं।

                   1
             1 -------------> 1
             |                | 
      2      |     1          |
0 ---------> 1 ----------> 0  |
|                          |  |
|     1            1       |  |
0 ---------> 0 ----------> 0  |
             |                |
      1      |      1         |
1 ---------> 0 -------------> 1

ध्यान दें कि प्रवाह ग्राफ में x नोड्स हैं, जबकि x बिट्स की संख्या है। और किनारों की अधिकतम संख्या (2 * x) -2 है।

तो 32 बिट पूर्णांक के लिए यह O (32) स्थान या O (1) स्थान लेगा।

अब यदि मैं 1,2,4 से शुरू होने वाली प्रत्येक संख्या के लिए क्षमता निकालता हूं तो मुझे अवशिष्ट ग्राफ के साथ छोड़ दिया जाता है।

0 ----------> 1 ---------> 1

अंत में मैं निम्नलिखित की तरह एक लूप चलाऊंगा,

 result = []
 for x in range(1,n):
     exists_path_in_residual_graph(x)
     result.append(x)

अब इसका परिणाम resultउन संख्याओं में होता है जो गायब नहीं होती हैं (झूठी सकारात्मक)। लेकिन के <= (परिणाम का आकार) <= एन जब kलापता तत्व होते हैं।

मैं दिए गए सूची के माध्यम से एक बार पिछली बार लापता परिणाम या नहीं चिह्नित करने के लिए जाना जाएगा।

तो समय जटिलता O (n) होगी।

अंत में, यह नोड्स लेकर झूठी सकारात्मक (और अंतरिक्ष) की आवश्यकता की संख्या को कम करने के लिए संभव है 00, 01, 11, 10बजाय बस की 0और 1


मैं आपके ग्राफ आरेख को नहीं समझता। नोड्स, किनारों और संख्याओं का क्या प्रतिनिधित्व करते हैं? क्यों कुछ किनारों को निर्देशित किया जाता है और दूसरों को नहीं?
dain

वास्तव में मैं वास्तव में आपके उत्तर को बिल्कुल नहीं समझता, क्या आप कुछ और स्पष्ट कर सकते हैं?
dain

1

आपको संभवतः O (k) के अर्थ पर स्पष्टीकरण की आवश्यकता होगी।

यहां मनमाना कश्मीर के लिए एक तुच्छ समाधान है: प्रत्येक v में आपके संख्याओं के लिए, 2 ^ v का योग जमा करें। अंत में, मैं 1 से एन तक लूप करता हूं। यदि 2 ^ i के साथ बिट बिटवाइंड एंडेड शून्य है, तो मैं गायब है। (या संख्यात्मक रूप से, यदि 2 ^ I से विभाजित होने वाली राशि का फर्श सम है। या sum modulo 2^(i+1)) < 2^i।)

आसान है, है ना? O (N) समय, O (1) संग्रहण, और यह मनमाना k का समर्थन करता है।

सिवाय इसके कि आप भारी संख्या की गणना कर रहे हैं कि एक वास्तविक कंप्यूटर पर प्रत्येक को O (N) स्थान की आवश्यकता होगी। वास्तव में, यह समाधान थोड़ा वेक्टर के समान है।

तो आप होशियार हो सकते हैं और योग और वर्गों की संख्या और क्यूब्स के योग की गणना कर सकते हैं ... v ^ k के योग तक, और परिणाम निकालने के लिए फैंसी गणित करें। लेकिन वे भी बड़ी संख्या में हैं, जो सवाल पूछते हैं: हम ऑपरेशन के किस सार मॉडल के बारे में बात कर रहे हैं? O (1) स्थान में कितना फिट बैठता है, और आपको कितने आकार की संख्याओं को योग करने में कितना समय लगता है?


अच्छा उत्तर! एक छोटी सी बात: "यदि राशि modulo 2 ^ i शून्य है, तो मैं गायब है" गलत है। लेकिन यह स्पष्ट है कि क्या इरादा है। मुझे लगता है कि "यदि राशि modulo 2 ^ (i + 1) 2 ^ i से कम है, तो मैं गायब है" सही होगा। (बेशक, अधिकांश प्रोग्रामिंग भाषाओं में हम मोड्यूलो गणना के बजाय बिट शिफ्टिंग का उपयोग करते हैं। कभी-कभी प्रोग्रामिंग भाषाएं सामान्य गणित संकेतन की तुलना में थोड़ी अधिक अभिव्यंजक होती हैं। :-))
jcsahnwaldt का कहना है कि GoFundMonit

1
धन्यवाद, आप पूरी तरह से सही हैं! फिक्स्ड, हालांकि मैं आलसी था और गणितीय संकेतन से भटका हुआ था ... ओह, और मैंने उसे भी गड़बड़ कर दिया। फिर से फिक्सिंग ...
sfink

1

यहाँ एक समाधान है जो sdcvvc के / Dimitris Andreou के उत्तर के रूप में जटिल गणित पर निर्भर नहीं करता है, इनपुट सरणी को कैफे और कर्नल पैनिक के रूप में नहीं बदलता है, और क्रिस लेचर, जेरेमीप के रूप में बड़े आकार के बिटसेट का उपयोग नहीं करता है और कई अन्य लोगों ने किया। मूल रूप से, मैंने Svalorzen / Gilad Deutch के विचार के लिए Q2 के साथ शुरुआत की, इसे सामान्य केस Qk के लिए सामान्यीकृत किया और जावा में कार्यान्वित किया ताकि यह साबित हो सके कि एल्गोरिथ्म काम करता है।

विचार

मान लीजिए कि हमें एक मनमाना अंतराल है मैं जिनमें से हम केवल पता है कि यह याद आ रही संख्या के कम से कम एक में शामिल है। एक इनपुट ऐरे से गुजरने के बाद, केवल I से संख्याओं को देखते हुए , हम S और S की मात्रा Q दोनों से लापता संख्या प्राप्त कर सकते हैं । हम हर बार I की लंबाई घटाते हुए करते हैं, जब भी हम I ( Q को प्राप्त करने के लिए ) से एक संख्या का सामना करते हैं और I में सभी संख्याओं की पूर्व-परिकलित राशि को घटाकर, उस समय की गई संख्या से ( S प्राप्त करने के लिए ) प्राप्त करते हैं ।

अब हम S और Q को देखते हैं । यदि Q = 1 , इसका मतलब है कि तब मेरे पास केवल एक लापता संख्या है, और यह संख्या स्पष्ट रूप से S है । हम I को समाप्त के रूप में चिह्नित करते हैं (इसे कार्यक्रम में "अस्पष्ट" कहा जाता है) और इसे आगे के विचार से छोड़ दें। दूसरी ओर, यदि Q> 1 , हम I में निहित गुम संख्याओं के औसत A = S / Q की गणना कर सकते हैं । के रूप में सभी नंबरों को अलग कर रहे हैं, इस तरह की संख्या कम से कम एक सख्ती से कम है एक और कम से कम एक से सख्ती से अधिक है एक । अब हमने I को A में विभाजित कियादो छोटे अंतरालों में जिनमें से प्रत्येक में कम से कम एक लापता संख्या है। ध्यान दें कि इससे कोई फर्क नहीं पड़ता कि हम किस अंतराल में A को असाइन करते हैं यह एक पूर्णांक है।

हम प्रत्येक अंतराल के लिए अलग-अलग (लेकिन एक ही पास में) S और Q की गणना करते हुए अगला सरणी पास बनाते हैं और उसके बाद Q = 1 के साथ अंतराल और Q> 1 के साथ अंतराल को विभाजित करते हैं । हम इस प्रक्रिया को तब तक जारी रखते हैं जब तक कि कोई नया "अस्पष्ट" अंतराल न हो, अर्थात हमारे पास विभाजित करने के लिए कुछ भी नहीं है क्योंकि प्रत्येक अंतराल में एक लापता संख्या है (और हम हमेशा इस संख्या को जानते हैं क्योंकि हम एस को जानते हैं )। हम एकमात्र "संपूर्ण रेंज" अंतराल से शुरू करते हैं जिसमें सभी संभावित संख्याएं होती हैं (जैसे प्रश्न में [1..N] )।

समय और स्थान की जटिलता का विश्लेषण

गुजरता की कुल संख्या पी हम जब तक प्रक्रिया बंद हो जाता है बनाने की जरूरत है याद आ रही संख्या गिनती की तुलना में कभी नहीं अधिक से अधिक है कश्मीर । असमानता p <= k को कठोरता से साबित किया जा सकता है। दूसरी ओर, एक अनुभवजन्य ऊपरी बाध्य पी <लॉग 2 एन + 3 भी है जो कश्मीर के बड़े मूल्यों के लिए उपयोगी है । हमें उस अंतराल को निर्धारित करने के लिए इनपुट सरणी की प्रत्येक संख्या के लिए एक द्विआधारी खोज करने की आवश्यकता है जिससे यह संबंधित है। यह लॉग k गुणक को समय जटिलता में जोड़ता है।

कुल में, समय जटिलता O (N k मिनट (k, log N) the log k) है । ध्यान दें कि बड़े k के लिए , यह sdcvvc / Dimitris Andreou की विधि से काफी बेहतर है, जो कि O (N (k) है

अपने काम के लिए, एल्गोरिथ्म को सबसे अधिक कश्मीर अंतराल पर भंडारण के लिए ओ (के) अतिरिक्त स्थान की आवश्यकता होती है , जो "बिटसेट" समाधान में ओ (एन) की तुलना में काफी बेहतर है ।

जावा कार्यान्वयन

यहां एक जावा वर्ग है जो उपरोक्त एल्गोरिथ्म को लागू करता है। यह हमेशा लापता संख्याओं की क्रमबद्ध सरणी देता है । कि इसके अलावा, यह की आवश्यकता नहीं है याद आ रही संख्या गिनती कश्मीर क्योंकि यह पहले पास में यह गणना करता है। संख्याओं की पूरी रेंज minNumberऔर maxNumberपैरामीटर (उदाहरण के लिए 1 और 100 प्रश्न में पहले उदाहरण के लिए) द्वारा दी गई है ।

public class MissingNumbers {
    private static class Interval {
        boolean ambiguous = true;
        final int begin;
        int quantity;
        long sum;

        Interval(int begin, int end) { // begin inclusive, end exclusive
            this.begin = begin;
            quantity = end - begin;
            sum = quantity * ((long)end - 1 + begin) / 2;
        }

        void exclude(int x) {
            quantity--;
            sum -= x;
        }
    }

    public static int[] find(int minNumber, int maxNumber, NumberBag inputBag) {
        Interval full = new Interval(minNumber, ++maxNumber);
        for (inputBag.startOver(); inputBag.hasNext();)
            full.exclude(inputBag.next());
        int missingCount = full.quantity;
        if (missingCount == 0)
            return new int[0];
        Interval[] intervals = new Interval[missingCount];
        intervals[0] = full;
        int[] dividers = new int[missingCount];
        dividers[0] = minNumber;
        int intervalCount = 1;
        while (true) {
            int oldCount = intervalCount;
            for (int i = 0; i < oldCount; i++) {
                Interval itv = intervals[i];
                if (itv.ambiguous)
                    if (itv.quantity == 1) // number inside itv uniquely identified
                        itv.ambiguous = false;
                    else
                        intervalCount++; // itv will be split into two intervals
            }
            if (oldCount == intervalCount)
                break;
            int newIndex = intervalCount - 1;
            int end = maxNumber;
            for (int oldIndex = oldCount - 1; oldIndex >= 0; oldIndex--) {
                // newIndex always >= oldIndex
                Interval itv = intervals[oldIndex];
                int begin = itv.begin;
                if (itv.ambiguous) {
                    // split interval itv
                    // use floorDiv instead of / because input numbers can be negative
                    int mean = (int)Math.floorDiv(itv.sum, itv.quantity) + 1;
                    intervals[newIndex--] = new Interval(mean, end);
                    intervals[newIndex--] = new Interval(begin, mean);
                } else
                    intervals[newIndex--] = itv;
                end = begin;
            }
            for (int i = 0; i < intervalCount; i++)
                dividers[i] = intervals[i].begin;
            for (inputBag.startOver(); inputBag.hasNext();) {
                int x = inputBag.next();
                // find the interval to which x belongs
                int i = java.util.Arrays.binarySearch(dividers, 0, intervalCount, x);
                if (i < 0)
                    i = -i - 2;
                Interval itv = intervals[i];
                if (itv.ambiguous)
                    itv.exclude(x);
            }
        }
        assert intervalCount == missingCount;
        for (int i = 0; i < intervalCount; i++)
            dividers[i] = (int)intervals[i].sum;
        return dividers;
    }
}

निष्पक्षता के लिए, यह वर्ग NumberBagवस्तुओं के रूप में इनपुट प्राप्त करता है । NumberBagसरणी संशोधन और यादृच्छिक अभिगम की अनुमति नहीं देता है और यह भी गिनता है कि अनुक्रमिक ट्रैवर्सिंग के लिए सरणी को कितनी बार अनुरोध किया गया था। यह बड़े सरणी परीक्षण के लिए भी अधिक उपयुक्त है Iterable<Integer>क्योंकि यह आदिम intमूल्यों के मुक्केबाजी से बचा जाता है और int[]एक सुविधाजनक परीक्षण की तैयारी के लिए एक बड़े हिस्से को लपेटने की अनुमति देता है । यह बदलने के लिए, अगर वांछित, कठिन नहीं है NumberBagद्वारा int[]या Iterable<Integer>में टाइप findहस्ताक्षर, foreach लोगों में उस में दो लोगों के लिए-छोरों बदलकर।

import java.util.*;

public abstract class NumberBag {
    private int passCount;

    public void startOver() {
        passCount++;
    }

    public final int getPassCount() {
        return passCount;
    }

    public abstract boolean hasNext();

    public abstract int next();

    // A lightweight version of Iterable<Integer> to avoid boxing of int
    public static NumberBag fromArray(int[] base, int fromIndex, int toIndex) {
        return new NumberBag() {
            int index = toIndex;

            public void startOver() {
                super.startOver();
                index = fromIndex;
            }

            public boolean hasNext() {
                return index < toIndex;
            }

            public int next() {
                if (index >= toIndex)
                    throw new NoSuchElementException();
                return base[index++];
            }
        };
    }

    public static NumberBag fromArray(int[] base) {
        return fromArray(base, 0, base.length);
    }

    public static NumberBag fromIterable(Iterable<Integer> base) {
        return new NumberBag() {
            Iterator<Integer> it;

            public void startOver() {
                super.startOver();
                it = base.iterator();
            }

            public boolean hasNext() {
                return it.hasNext();
            }

            public int next() {
                return it.next();
            }
        };
    }
}

टेस्ट

इन वर्गों के उपयोग को प्रदर्शित करने वाले सरल उदाहरण नीचे दिए गए हैं।

import java.util.*;

public class SimpleTest {
    public static void main(String[] args) {
        int[] input = { 7, 1, 4, 9, 6, 2 };
        NumberBag bag = NumberBag.fromArray(input);
        int[] output = MissingNumbers.find(1, 10, bag);
        System.out.format("Input: %s%nMissing numbers: %s%nPass count: %d%n",
                Arrays.toString(input), Arrays.toString(output), bag.getPassCount());

        List<Integer> inputList = new ArrayList<>();
        for (int i = 0; i < 10; i++)
            inputList.add(2 * i);
        Collections.shuffle(inputList);
        bag = NumberBag.fromIterable(inputList);
        output = MissingNumbers.find(0, 19, bag);
        System.out.format("%nInput: %s%nMissing numbers: %s%nPass count: %d%n",
                inputList, Arrays.toString(output), bag.getPassCount());

        // Sieve of Eratosthenes
        final int MAXN = 1_000;
        List<Integer> nonPrimes = new ArrayList<>();
        nonPrimes.add(1);
        int[] primes;
        int lastPrimeIndex = 0;
        while (true) {
            primes = MissingNumbers.find(1, MAXN, NumberBag.fromIterable(nonPrimes));
            int p = primes[lastPrimeIndex]; // guaranteed to be prime
            int q = p;
            for (int i = lastPrimeIndex++; i < primes.length; i++) {
                q = primes[i]; // not necessarily prime
                int pq = p * q;
                if (pq > MAXN)
                    break;
                nonPrimes.add(pq);
            }
            if (q == p)
                break;
        }
        System.out.format("%nSieve of Eratosthenes. %d primes up to %d found:%n",
                primes.length, MAXN);
        for (int i = 0; i < primes.length; i++)
            System.out.format(" %4d%s", primes[i], (i % 10) < 9 ? "" : "\n");
    }
}

बड़े सरणी परीक्षण इस तरह से किया जा सकता है:

import java.util.*;

public class BatchTest {
    private static final Random rand = new Random();
    public static int MIN_NUMBER = 1;
    private final int minNumber = MIN_NUMBER;
    private final int numberCount;
    private final int[] numbers;
    private int missingCount;
    public long finderTime;

    public BatchTest(int numberCount) {
        this.numberCount = numberCount;
        numbers = new int[numberCount];
        for (int i = 0; i < numberCount; i++)
            numbers[i] = minNumber + i;
    }

    private int passBound() {
        int mBound = missingCount > 0 ? missingCount : 1;
        int nBound = 34 - Integer.numberOfLeadingZeros(numberCount - 1); // ceil(log_2(numberCount)) + 2
        return Math.min(mBound, nBound);
    }

    private void error(String cause) {
        throw new RuntimeException("Error on '" + missingCount + " from " + numberCount + "' test, " + cause);
    }

    // returns the number of times the input array was traversed in this test
    public int makeTest(int missingCount) {
        this.missingCount = missingCount;
        // numbers array is reused when numberCount stays the same,
        // just Fisher–Yates shuffle it for each test
        for (int i = numberCount - 1; i > 0; i--) {
            int j = rand.nextInt(i + 1);
            if (i != j) {
                int t = numbers[i];
                numbers[i] = numbers[j];
                numbers[j] = t;
            }
        }
        final int bagSize = numberCount - missingCount;
        NumberBag inputBag = NumberBag.fromArray(numbers, 0, bagSize);
        finderTime -= System.nanoTime();
        int[] found = MissingNumbers.find(minNumber, minNumber + numberCount - 1, inputBag);
        finderTime += System.nanoTime();
        if (inputBag.getPassCount() > passBound())
            error("too many passes (" + inputBag.getPassCount() + " while only " + passBound() + " allowed)");
        if (found.length != missingCount)
            error("wrong result length");
        int j = bagSize; // "missing" part beginning in numbers
        Arrays.sort(numbers, bagSize, numberCount);
        for (int i = 0; i < missingCount; i++)
            if (found[i] != numbers[j++])
                error("wrong result array, " + i + "-th element differs");
        return inputBag.getPassCount();
    }

    public static void strideCheck(int numberCount, int minMissing, int maxMissing, int step, int repeats) {
        BatchTest t = new BatchTest(numberCount);
        System.out.println("╠═══════════════════════╬═════════════════╬═════════════════╣");
        for (int missingCount = minMissing; missingCount <= maxMissing; missingCount += step) {
            int minPass = Integer.MAX_VALUE;
            int passSum = 0;
            int maxPass = 0;
            t.finderTime = 0;
            for (int j = 1; j <= repeats; j++) {
                int pCount = t.makeTest(missingCount);
                if (pCount < minPass)
                    minPass = pCount;
                passSum += pCount;
                if (pCount > maxPass)
                    maxPass = pCount;
            }
            System.out.format("║ %9d  %9d  ║  %2d  %5.2f  %2d  ║  %11.3f    ║%n", missingCount, numberCount, minPass,
                    (double)passSum / repeats, maxPass, t.finderTime * 1e-6 / repeats);
        }
    }

    public static void main(String[] args) {
        System.out.println("╔═══════════════════════╦═════════════════╦═════════════════╗");
        System.out.println("║      Number count     ║      Passes     ║  Average time   ║");
        System.out.println("║   missimg     total   ║  min  avg   max ║ per search (ms) ║");
        long time = System.nanoTime();
        strideCheck(100, 0, 100, 1, 20_000);
        strideCheck(100_000, 2, 99_998, 1_282, 15);
        MIN_NUMBER = -2_000_000_000;
        strideCheck(300_000_000, 1, 10, 1, 1);
        time = System.nanoTime() - time;
        System.out.println("╚═══════════════════════╩═════════════════╩═════════════════╝");
        System.out.format("%nSuccess. Total time: %.2f s.%n", time * 1e-9);
    }
}

Ideone पर उन्हें बाहर की कोशिश करो


0

मेरा मानना है कि मैं एक है O(k)समय और O(log(k))तुम हो कि दिए गए स्थान एल्गोरिथ्म, floor(x)और log2(x)मनमाने ढंग से बड़ा उपलब्ध पूर्णांकों के लिए कार्य करता है:

आपके पास एक kलंबी-लंबी पूर्णांक (इसलिए log8(k)स्थान) है जहाँ आप जोड़ते हैं x^2, जहाँ x अगली संख्या है जो आपको बैग में मिलती है: s=1^2+2^2+...इसमें O(N)समय लगता है (जो साक्षात्कारकर्ता के लिए कोई समस्या नहीं है)। सबसे अंत में आपको j=floor(log2(s))वह नंबर मिलता है, जिसकी सबसे बड़ी संख्या आप खोज रहे हैं। तब s=s-jऔर आप फिर से ऊपर करते हैं:

for (i = 0 ; i < k ; i++)
{
  j = floor(log2(s));
  missing[i] = j;
  s -= j;
}

अब, आपके पास आमतौर पर फ़्लोर-लॉगर्स के लिए फ़्लोर और लॉग 2 फ़ंक्शंस नहीं होते 2756हैं, बल्कि डबल्स के लिए होते हैं। इसलिए? बस, प्रत्येक 2 बाइट्स (या 1, या 3, या 4) के लिए आप वांछित संख्याएँ प्राप्त करने के लिए इन कार्यों का उपयोग कर सकते हैं, लेकिन यह O(N)समय जटिलता के लिए एक कारक जोड़ता है


0

यह बेवकूफ लग सकता है, लेकिन, आपके सामने प्रस्तुत पहली समस्या में, आपको वास्तव में उस समीकरण का उपयोग करके लापता संख्या को खोजने के लिए बैग में शेष सभी संख्याओं को देखना होगा।

इसलिए, चूंकि आपको सभी नंबर देखने को मिलते हैं, बस उस नंबर की तलाश करें जो गायब है। जब दो नंबर गायब होते हैं तो वही होता है। बहुत आसान है मुझे लगता है। एक समीकरण का उपयोग करने का कोई मतलब नहीं है जब आपको बैग में शेष संख्याएं देखने को मिलती हैं।


2
मुझे लगता है कि उन्हें संक्षेप में रखने का लाभ यह है कि आपको यह याद रखने की जरूरत नहीं है कि आपने पहले से कौन सी संख्या देखी है (उदाहरण के लिए, कोई अतिरिक्त मेमोरी की आवश्यकता नहीं है)। अन्यथा एकमात्र विकल्प है सभी देखे गए मूल्यों का एक सेट बनाए रखना और फिर उस सेट पर पुनरावृति करना जो गायब है उसे ढूंढना।
दान ताओ

3
यह सवाल आमतौर पर ओ (1) अंतरिक्ष जटिलता के वजीफा के साथ पूछा जाता है।

पहली N संख्याओं का योग N (N + 1) / 2 है। एन = 100, सम = 100 * (101) / 2 = 5050 के लिए;
tmarthal

0

मुझे लगता है कि इसे इस तरह सामान्यीकृत किया जा सकता है:

अंक एस, एम अंकगणित श्रृंखला और गुणा के योग के लिए प्रारंभिक मान के रूप में।

S = 1 + 2 + 3 + 4 + ... n=(n+1)*n/2
M = 1 * 2 * 3 * 4 * .... * n 

मुझे इसकी गणना करने के लिए एक सूत्र के बारे में सोचना चाहिए, लेकिन वह बात नहीं है। वैसे भी, यदि एक नंबर गायब है, तो आप पहले से ही समाधान प्रदान करते हैं। हालाँकि, यदि दो नंबर गायब हैं, तो आइए S1 और M1 द्वारा नई योग और कुल बहु को निरूपित करें, जो निम्नानुसार होगा:

S1 = S - (a + b)....................(1)

Where a and b are the missing numbers.

M1 = M - (a * b)....................(2)

चूँकि आप S1, M1, M और S को जानते हैं, उपरोक्त समीकरण a और b, लापता संख्याओं को खोजने के लिए हल करने योग्य है।

अब तीन नंबर गायब हैं:

S2 = S - ( a + b + c)....................(1)

Where a and b are the missing numbers.

M2 = M - (a * b * c)....................(2)

अब आपका अज्ञात 3 है जबकि आपके पास बस दो समीकरण हैं जिनसे आप हल कर सकते हैं।


गुणन हालांकि काफी बड़ा हो जाता है .. इसके अलावा, आप 2 से अधिक लापता संख्याओं को कैसे सामान्य करते हैं?
थॉमस अहले

मैंने इन सूत्रों को N = 3 और लापता संख्या = {1, 2} के साथ बहुत ही सरल क्रम पर आज़माया है। मैंने काम नहीं किया, क्योंकि मेरा मानना ​​है कि त्रुटि सूत्र (2) में है जिसे पढ़ना चाहिए M1 = M / (a * b)( उस उत्तर को देखें )। तब यह ठीक काम करता है।
dma_k

0

मुझे नहीं पता कि यह कुशल है या नहीं लेकिन मैं इस समाधान का सुझाव देना चाहूंगा।

  1. 100 तत्वों की गणना करें
  2. 98 तत्वों की गणना xor (2 तत्वों को हटाने के बाद)
  3. अब (1 का परिणाम) XOR (2 का परिणाम) आपको दो लापता नोस i..ea XOR b का एक्स प्रदान करता है यदि a और b अनुपस्थित तत्व हैं।
    अपने सामान्य दृष्टिकोण के साथ लापता Nos का योग प्राप्त करें। योग सूत्र भिन्न होता है और यह कहता है कि अंतर d है।

अब संभव जोड़े (p, q) दोनों को प्राप्त करने के लिए एक लूप चलाएं, जिसमें दोनों [1, 100] और d के योग हैं।

जब एक जोड़ी प्राप्त की जाती है, तो जांच करें कि क्या (3 का परिणाम) XOR p = q और यदि हां तो हम कर रहे हैं।

कृपया मुझे सही करें अगर मैं गलत हूं और अगर यह सही है तो समय की जटिलता पर भी टिप्पणी करें


2
मुझे नहीं लगता कि योग और एक्सआर विशिष्ट रूप से दो संख्याओं को परिभाषित करते हैं। सभी संभावित k-tuples को प्राप्त करने के लिए एक लूप चलाना जो D के लिए समय लेता है O (C (n, k-1)) = O (n <sup> k-1 </ sup>), जो k> 2 के लिए, बुरा है।
तेयपेम सेप

0

हम ज्यादातर समय Q1 और Q2 में (log n) कर सकते हैं।

मान लीजिए कि हमारी संख्या में memory chipसरणी होती nहै test tubes। और xटेस्ट ट्यूब में एक संख्या x milliliterको रासायनिक-तरल द्वारा दर्शाया जाता है।

मान लीजिए हमारा प्रोसेसर एक है laser light। जब हम लेज़र को प्रकाश में लाते हैं तो यह लम्बाई तक सभी नलियों को पीछे छोड़ देता है। हर बार जब यह रासायनिक तरल से गुजरता है, तो चमक कम हो जाती है 1। और कुछ मिलीमीटर के निशान पर प्रकाश को पारित करना एक ऑपरेशन है O(1)

अब अगर हम टेस्ट-ट्यूब के बीच में अपने लेज़र को हल्का करते हैं और चमकदारता का उत्पादन प्राप्त करते हैं

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

हम उपरोक्त प्रक्रिया को फिर से दोहरा सकते हैं और अपनी समस्या डोमेन को संकुचित कर सकते हैं। प्रत्येक चरण में, हम डोमेन को आधे से छोटा करते हैं। और अंत में हम अपने परिणाम पर पहुँच सकते हैं।

समानांतर एल्गोरिदम जो ध्यान देने योग्य हैं (क्योंकि वे दिलचस्प हैं),

  • कुछ समानांतर एल्गोरिदम द्वारा छँटाई, उदाहरण के लिए, O(log^3 n)समय में समानांतर मर्ज किया जा सकता है । और फिर लापता संख्या को O(log n)समय में बाइनरी खोज द्वारा पाया जा सकता है ।
  • सैद्धांतिक रूप से, यदि हमारे पास nप्रोसेसर है तो प्रत्येक प्रक्रिया एक इनपुट की जांच कर सकती है और कुछ ध्वज सेट कर सकती है जो संख्या (आसानी से किसी सरणी में) की पहचान करती है। और अगले चरण में प्रत्येक प्रक्रिया प्रत्येक ध्वज की जांच कर सकती है और अंत में उस संख्या को आउटपुट कर सकती है जिसे ध्वजांकित नहीं किया गया है। पूरी प्रक्रिया में O(1)समय लगेगा। इसके पास अतिरिक्त O(n)स्थान / स्मृति आवश्यकता है।

ध्यान दें, कि ऊपर दिए गए दो समानांतर एल्गोरिदम को टिप्पणी में वर्णित अतिरिक्त स्थान की आवश्यकता हो सकती है


जबकि टेस्ट-ट्यूब-लेजर विधि वास्तव में दिलचस्प है, मुझे आशा है कि आप सहमत हैं कि यह हार्डवेयर निर्देशों का अच्छी तरह से अनुवाद नहीं करता है और इसलिए O(logn)कंप्यूटर पर होने की संभावना नहीं है ।
सिरग्यू

1
जैसे कि आपकी छँटाई विधि के लिए, जो अतिरिक्त स्थान की मात्रा पर निर्भर करेगा N, और O(N)समय से अधिक (इसकी निर्भरता के संदर्भ में N), जिसे हम बेहतर से बेहतर करने का इरादा कर रहे हैं।
सिरग्यू

@SirGuy मैं टेस्ट-ट्यूब अवधारणा और समानांतर प्रसंस्करण स्मृति लागत के बारे में आपकी चिंता की सराहना करता हूं। मेरी पोस्ट समस्या के बारे में अपने विचार साझा करने के लिए है। GPU प्रोसेसर अब समानांतर प्रसंस्करण संभव कर रहे हैं। कौन जानता है, अगर टेस्ट-ट्यूब अवधारणा भविष्य में उपलब्ध नहीं होगी।
शुवा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.