O (nlogn) एलगोरिदम - बाइनरी स्ट्रिंग के भीतर तीन समान रूप से अंतर वाले खोजें


173

कल एक एल्गोरिथम परीक्षण पर मेरा यह प्रश्न था, और मैं इसका उत्तर नहीं दे सकता। यह मुझे बिल्कुल पागल कर रहा है, क्योंकि यह लगभग 40 अंकों के लायक था। मुझे लगता है कि अधिकांश वर्ग ने इसे सही ढंग से हल नहीं किया है, क्योंकि मैं पिछले 24 घंटों में एक समाधान के साथ नहीं आया हूं।

लंबाई n के एक मनमाने ढंग से बाइनरी स्ट्रिंग को देखते हुए, यदि वे मौजूद हैं, तो स्ट्रिंग के भीतर तीन समान रूप से रिक्त स्थान खोजें। एक एल्गोरिथ्म लिखें जो इसे O (n * log (n)) समय में हल करता है।

तो इन तारों की तरह तीन हैं जो "समान रूप से दूरी" हैं: 11100000, 0100100100

संपादित करें: यह एक यादृच्छिक संख्या है, इसलिए इसे किसी भी संख्या में काम करने में सक्षम होना चाहिए। मैंने जो उदाहरण दिए, वे "समान रूप से प्रायोजित" संपत्ति का वर्णन करने के लिए थे। तो 1001011 एक वैध संख्या है। 1, 4, और 7 के साथ जो समान रूप से दूरी पर हैं।


4
निम्नलिखित संभव है: 10011010000? इसमें तीन 1s (पहला, दूसरा, आगे) समान रूप से फैला हुआ है, लेकिन अतिरिक्त 1s भी हैं।
अन्ना

5
रॉबर्ट, आपको अपने प्रोफेसर को इसके लिए जवाब देने और इसे यहां पोस्ट करने की आवश्यकता है। यह समस्या मुझे दीवार तक पहुंचा रही है। मैं यह पता लगा सकता हूं कि इसे n ^ 2 में कैसे किया जाए लेकिन n * log (n) नहीं।
जेम्स मैकमोहन

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

2
यदि आपका प्रोफेसर कोई समाधान देता है तो कृपया उसे उत्तर के रूप में पोस्ट करें।
ldog

5
इस तथ्य को ध्यान में रखते हुए कि क्लॉस रोथ को प्रत्येक अन्य के लिए फील्ड मेडल 1958 (अन्य बातों के साथ) साबित हुआ कि प्रत्येक घनत्व d> 0 के लिए एक प्राकृतिक संख्या N ऐसी है, जिसमें कम से कम d * के साथ {1, ..., N} का प्रत्येक उपसमूह है। एन तत्वों में लंबाई 3 की अंकगणितीय प्रगति शामिल है, मुझे आश्चर्य नहीं है कि अब तक किसी ने समस्या के लिए एक ठोस एल्गोरिथ्म नहीं पाया है। En.wikipedia.org/wiki/Szemer%C3%A9di%27s_theorem
jp

जवाबों:


128

आखिरकार! बाद sdcvvc के उत्तर की ओर जाता है , हमारे पास यह है: समस्या के लिए O (n log n) एल्गोरिदम! इसे समझने के बाद भी यह सरल है। जिन लोगों ने एफएफटी का अनुमान लगाया वे सही थे।

समस्या: हमें Sलंबाई n का एक बाइनरी स्ट्रिंग दिया जाता है , और हम इसमें तीन समान रूप से 1 s स्थान प्राप्त करना चाहते हैं। उदाहरण के लिए, Sहो सकता है 110110010, जहां n = 9। यह समान रूप से 2, 5 और 8 के स्थान पर 1 स्थान पर है।

  1. Sबाएं से दाएं स्कैन करें , और L1. के पदों की एक सूची बनाएं । S=110110010उपरोक्त के लिए, हमारे पास L = [1, 2, 4, 5, 8] सूची है। यह चरण O (n) है। समस्या एक को खोजने के लिए अब है लंबाई 3 के अंकगणितीय प्रगति में L, यानी अलग लगता है एक, ख, ग में Lऐसी है कि बा = सीबी , या समतुल्य एक + c = 2 बी । ऊपर के उदाहरण के लिए, हम प्रगति (2, 5, 8) को खोजना चाहते हैं।

  2. एक बनाओ बहुपद p शर्तों से एक्स कश्मीर प्रत्येक के लिए कश्मीर में L। ऊपर के उदाहरण के लिए, हम बहुपद p (x) = (x + x 2 + x 4 + x 5 + x 8 ) बनाते हैं । यह चरण O (n) है।

  3. फास्ट फूरियर ट्रांसफॉर्म का उपयोग करके बहुपद q= पी 2 का पता लगाएं । ऊपर दिए गए उदाहरण के लिए, हमें बहुपद q (x) = x 16 + 2x 13 + 2x 12 + 3x 10 + 4x 9 + x 8 + 2x 7 + 4x 6 + 2x 5 + x 4 + 2x 3 + x 2 मिलते हैंयह चरण O (n log n) है।

  4. करने के लिए इसी को छोड़कर अन्य सभी शर्तों पर ध्यान न दें एक्स 2k कुछ के लिए कश्मीर में L। ऊपर दिए गए उदाहरण के लिए, हमें x 16 , 3x 10 , x 8 , x 4 , x 2 मिलते हैं । यह चरण O (n) है, यदि आप इसे करना चाहते हैं।

यहाँ महत्वपूर्ण बिंदु है: किसी भी गुणांक एक्स 2 बी के लिए में Lहै ठीक जोड़े की संख्या (एक, ग) में Lऐसी है कि एक + c = 2 बी । [CLRS, Ex। 30.1-7] एक ऐसी जोड़ी है (बी, बी) हमेशा (इसलिए गुणांक कम से कम 1 है), लेकिन अगर कोई अन्य जोड़ी (ए, सी) मौजूद है , तो गुणांक कम से कम 3 है, (ए, सी से) ) और (सी, ए) । ऊपर के उदाहरण के लिए, हमारे पास ए पी (2,5,8) के कारण x 10 का गुणांक 3 ठीक है। (ये गुणांक x 2bऊपर दिए गए कारणों के लिए हमेशा विषम संख्या होगी। और q में अन्य सभी गुणांक हमेशा रहेंगे।)

तो फिर, एल्गोरिथ्म इन शर्तों के गुणांक x 2b को देखने के लिए है, और देखें कि क्या उनमें से कोई भी 1 से अधिक है। यदि कोई नहीं है, तो समान रूप से 1 एस नहीं हैं। अगर वहाँ है एक में Lहै जिसके लिए के गुणांक एक्स 2 बी 1 से अधिक है, तो हम जानते हैं कि कुछ जोड़ी है कि वहाँ (क, ग) - के अलावा अन्य (ख, ख) के लिए जो - एक + c = 2 बी । वास्तविक जोड़ी खोजने के लिए, हम बस प्रत्येक कोशिश एक में L(इसी होगा 2 बी-एक ) और अगर वहाँ एक 1 स्थान पर है देखना 2 बी-एक में S। यह चरण O (n) है।

बस आज के लिए इतना ही।


एक पूछ सकता है: क्या हमें एफएफटी का उपयोग करने की आवश्यकता है? जैसे कई जवाब, बीटा के , flybywire की , और आरएसपी के सुझाव है कि दृष्टिकोण है कि चेकों 1s की प्रत्येक जोड़ी और अगर वहाँ "तीसरे" स्थिति में एक 1 देखता है, हे में हो सकता है काम (एन एन लॉग इन करें), अंतर्ज्ञान के आधार पर अगर बहुत अधिक 1s हैं, तो हमें आसानी से एक ट्रिपल मिल जाएगा, और यदि बहुत कम 1s हैं, तो सभी जोड़ों की जांच में बहुत कम समय लगता है। दुर्भाग्य से, जबकि इस अंतर्ज्ञान सही है और सरल दृष्टिकोण है O (n की तुलना में बेहतर 2 ), यह नहीं काफी बेहतर है। जैसा कि sdcvvc के उत्तर में , हम लंबाई n = 3 k के तारों का "कैंटर जैसा सेट" ले सकते हैं1s के साथ उन पदों पर जिनका टर्नरी प्रतिनिधित्व केवल 0s और 2s (कोई 1s) है। इस तरह के तार में 2 k = n (लॉग 2) / (लॉग 3) 63 n 0.63 होते हैं और इसमें समान रूप से 1 s नहीं होता है, इसलिए सभी जोड़े की जाँच करना 1s की संख्या के वर्ग के क्रम का होगा: 4 k pt n 1.26 जो दुर्भाग्य से asymptotically से बड़ा है (n log n)। वास्तव में, सबसे खराब स्थिति और भी बदतर है: 1953 में लियो मोजर ने ऐसे तार का निर्माण किया (प्रभावी रूप से) जिनमें एन 1-सी /) (लॉग एन) 1 एस है लेकिन समान रूप से 1 एस नहीं है, जिसका अर्थ है कि इस तरह के तारों पर, सरल दृष्टिकोण √ ( n 2-2c / log (लॉग एन) ले जाएगा )- केवल एक छोटा सा Θ (n 2 ) से बेहतर है , आश्चर्यजनक रूप से!


लंबाई के एक स्ट्रिंग में अधिकतम 1 के बारे में n जिसमें 3 समान रूप से नहीं हैं (जो हमने ऊपर देखा था आसान कैंटर जैसे निर्माण से कम से कम n 0.63 था, और कम से कम n 1-c / √ (लॉग एन) के साथ मोजर का निर्माण) - यह OEIS A003002 है । इसकी गणना सीधे OEIS A065825 से k के रूप में की जा सकती है जैसे A065825 (k) A n <A065825 (k + 1)। मैंने उन्हें खोजने के लिए एक कार्यक्रम लिखा था, और यह पता चला कि लालची एल्गोरिथ्म सबसे लंबे समय तक ऐसी स्ट्रिंग नहीं देता है। उदाहरण के लिए, n = 9 के लिए, हम 5 1s (110100011) प्राप्त कर सकते हैं, लेकिन लालची केवल 4 (110110000) देता है, n के लिए= 26 हम 11 1s (11001010001000010110001101) प्राप्त कर सकते हैं, लेकिन लालची केवल 8 (11011000011011000000000000) देता है, और n = 74 के लिए हम 22 1 प्राप्त कर सकते हैं (1100001100010101010101000000000000010100000001010100000000), लेकिन लालच से लालच देता है, लेकिन लालच देता है। वे 50 (जब तक कि सभी 38 से 50) तक काफी कुछ स्थानों पर सहमत होते हैं, हालांकि। जैसा कि OEIS संदर्भ कहता है, ऐसा लगता है कि Jaroslaw Wroblewski इस प्रश्न में रुचि रखता है, और वह इन गैर-औसत सेटों पर एक वेबसाइट रखता है । सटीक संख्या केवल 194 तक ज्ञात है।


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

4
खैर, चरण 1, एपी को खोजने के लिए समस्या का अनुवाद करते हुए, सीधा है। चरण 3, कि बहुपद को O (n log n) समय में गुणा किया जा सकता है, यह एक तथ्य है। वास्तविक चाल, और जो समस्या को कठिन बना देती है, वह है 11011 के विचार को बहुपदों के साथ गुणांक के रूप में [1,1,0,1,1], आदि। यह एक चतुर और अक्सर उपयोगी विचार है, जो सभी को जाता है वापस यूलर की तरफ। [आधुनिक प्रदर्शनी के लिए विल्फ की भयानक पुस्तक " जेनरफंक्शनोलॉजी " देखें: math.upenn.edu/~wilf/DownldGF.html ] तो यह इस बात पर निर्भर करता है कि छात्रों को हाल की स्मृति में कार्य उत्पन्न करने के लिए उजागर किया गया था या नहीं। :-)
श्रीवत्सआर

2
क्षमा करें, मेरी गणना पूरी तरह से गलत है। यह 110110010 ^ 2 = 12124214302200100 होनी चाहिए। लेकिन विचार खड़ा है। बस 3. की ​​स्थिति पर ध्यान दें
गिलर्मो फिलिप्स

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

1
@RexE: यदि p डिग्री n-1 का है (n शब्द है), q = p ^ 2 डिग्री 2n-2 का है (अधिकतम 2n-1 शब्दों में है)। आपको n ^ 2 कैसे मिला? (इसके अलावा, एफएफटी का उपयोग करके ओ (एन लॉग एन) समय में डिग्री एन के दो बहुपदों को गुणा करना एक मानक मानक ऑपरेशन है; कृपया जवाब में लिंक पर क्लिक करें या विकिपीडिया लेख देखें ।)
श्रीवत्सआर

35

आपकी समस्या को इस पत्र में AVERAGE कहा जाता है (1999):

एक समस्या 3SUM- कठिन है यदि समस्या से एक उप-द्विघात कमी है 3SUM: एक सेट A के पूर्णांक को देखते हुए, क्या ए, बी, सी में ऐसे तत्व हैं जो a + b + c = 0 है? यह ज्ञात नहीं है कि AVERAGE 3SUM- हार्ड है या नहीं। हालाँकि, AVERAGE से 3SUM तक एक सरल रैखिक-समय में कमी है, जिसका वर्णन हम छोड़ते हैं।

विकिपीडिया :

जब पूर्णांक सीमा में होते हैं [inteu ... u], 3SUM को समय O (n + u lg u) में हल किया जा सकता है S को थोड़ा वेक्टर के रूप में दर्शाकर और FFT का उपयोग करके एक कनवल्शन का प्रदर्शन किया जाता है।

यह आपकी समस्या को हल करने के लिए पर्याप्त है :)।

यह बहुत महत्वपूर्ण है कि ओ (एन लॉग एन) शून्य और लोगों की संख्या के मामले में जटिलता है, न कि उन की गिनती (जो एक सरणी के रूप में दी जा सकती है, जैसे [1,5,9,15])। अगर एक सेट में अंकगणितीय प्रगति है, तो जाँच करना, 1 की संख्या की शर्तें कठिन हैं, और 1999 के अनुसार उस पेपर के अनुसार O (n 2 ) की तुलना में कोई तेज़ एल्गोरिथम ज्ञात नहीं है, और अनुमान लगाया जाता है कि यह मौजूद नहीं है। हर कोई जो इसे नहीं लेता है, वह एक खुली समस्या को हल करने का प्रयास कर रहा है।

अन्य दिलचस्प जानकारी, ज्यादातर अपरिवर्तनीय:

निम्न परिबंध:

एक आसान निचली सीमा है कैंटर जैसा सेट (संख्या 1..3 ^ n-1 जिनके टर्नरी विस्तार में 1 नहीं है) - इसका घनत्व n ^ (log_3 2) (लगभग 0.631) है। यदि सेट बहुत बड़ा नहीं है, तो किसी भी जाँच और फिर सभी जोड़े की जाँच करने के लिए O (n लॉग एन) प्राप्त करने के लिए पर्याप्त नहीं है। आपको सीक्वेंस स्मार्ट की जांच करनी होगी। एक बेहतर निचली सीमा को यहाँ उद्धृत किया गया है - यह n 1-c / (log (n)) ^ (1/2) है । इसका मतलब है कि कैंटर सेट इष्टतम नहीं है।

ऊपरी बाध्य - मेरा पुराना एल्गोरिथ्म:

यह ज्ञात है कि बड़े n के लिए, {1,2, ..., n} के एक उपसमूह जिसमें अंकगणितीय प्रगति नहीं है, में अधिकांश n / (log n) ^ (1/20) तत्व हैं। पेपर अंकगणितीय प्रगति में त्रिकोणीय पर अधिक साबित होता है: सेट में n * 2 28 * (लॉग लॉग एन / लॉग एन) 1/2 तत्वों से अधिक नहीं हो सकता है । तो आप जाँच कर सकते हैं कि क्या यह बाउंड हासिल किया गया है और यदि नहीं, तो भोले जोड़े की जाँच करें। यह O (n 2 * log लॉग एन / लॉग एन) एल्गोरिथ्म है, जो O (n 2 ) से तेज है । दुर्भाग्य से "ऑन ट्रिपल्स ..." स्प्रिंगर पर है - लेकिन पहला पेज उपलब्ध है, और बेन ग्रीन का एक्सपोजर यहां उपलब्ध है , पेज 28, प्रमेय 24।

वैसे, कागजात 1999 से हैं - उसी वर्ष जैसा कि मैंने पहले उल्लेख किया था, इसलिए शायद पहले वाले ने उस परिणाम का उल्लेख नहीं किया है।


2
महान जवाब, पहला जो इस समस्या के बारे में निश्चित कुछ भी कहता है। तो कैंटर जैसे सेट में n ^ 0.63 1 s है, जिसका अर्थ है कि "1s के सभी जोड़े की जाँच करें" एल्गोरिथ्म सबसे खराब स्थिति में कम से कम n ^ 1.26 (≫ n लॉग एन) है। कम (btw मोजर कागज वह उद्धरण यहाँ उपलब्ध है: Szemeredi के समाचार पत्र में उद्धृत बाध्य books.google.com/books?id=Cvtwu5vVZF4C&pg=PA245 ) वास्तव में मतलब n ^ (2-ओ (1)) करने लगता है, लेकिन हमें चाहिए थोड़ा सावधान रहें क्योंकि वहाँ हमारे पास {1, ..., n} से संख्याएँ हैं, लेकिन यहाँ यह अनुक्रम में संख्याओं का योग है जो n है।
श्रीवत्सआर

एर, वास्तव में "कैंटर जैसा" बाइनरी अनुक्रम क्या है जिसमें n ^ (log_3 2) 1s है और इसमें कोई तीन समान रूप से 1 s नहीं है?
श्रीवत्सआर

उदाहरण: 101000101000000000101000101। इसकी लंबाई 3 ^ n है, और 2 ^ n वाले (इसलिए n ^ 0.63 घनत्व) है। यदि आप बाइनरी में 1 के स्थानों को लिखते हैं, तो यह {0,2,20,22,200,202,220,222} होगा। इसके बारे में सोचने का एक और संभावित तरीका है एक क्रम लेना, और लगातार "मध्य" को हटा दें जैसा कि सामान्य कैंटर सेट निर्माण में होता है: 111111111 -> 111000111 -> 101000101। इसका कारण अंकगणितीय प्रगति नहीं है: यदि x , y, z का गठन एक है, तो y = (x + z) / 2 और x और z कुछ विस्तार स्थान पर भिन्न हैं। सबसे महत्वपूर्ण एक ले लो। Say x में 0 है और z में 2 है। फिर y के पास 1 होना चाहिए। अंतर्विरोध।
sdcvvc

3
फिर, महान शोध! मैंने 2008 के 3SUM पेपर का अनुसरण किया, और इसने CLRS व्यायाम का उल्लेख किया। 30.1-7, जिसे देखने के बाद मुझे जवाब मिला - ओ (एन लॉग एन) एल्गोरिदम वास्तव में काफी सरल है! (बस एक बहुपद / जननक्रिया को स्क्वर करते हुए।) मैंने नीचे उत्तर दिया है। (अब इसके बारे में पहले से विचार न करने के लिए खुद को लात मारना ... सरल समाधान हमेशा उस प्रतिक्रिया को मिटा देते हैं: पी)
श्रीवत्सआर

तो, उनकी परीक्षा के प्रश्न का उत्तर कुछ इस तरह था, "यह समस्या 3-SUM हार्ड समस्या के प्रति reducible है, और 3-SUM हार्ड का कोई उप-द्विघात समाधान नहीं है, इसलिए इस समस्या को O (n logn) में हल नहीं किया जा सकता है। " हाँ?
हुग्डब्रोर्न

8

यह एक समाधान नहीं है, लेकिन ओलेक्सि क्या सोच रहा था , इसी तरह की एक पंक्ति थी

मैं अधिकतम संख्या के साथ अनुक्रम बनाने के साथ खेल रहा था, और वे सभी काफी दिलचस्प हैं, मैं 125 अंकों तक गया और यहां पहले 3 नंबर हैं, जो संभव के रूप में कई '1' बिट्स सम्मिलित करने का प्रयास करते हैं:

  • 11011000011011000000000000001101100001101100000000000000000000000000000000000000000110110000110110000000000000011011000011011
  • 10110100010110100000000000010110100010110100000000000000000000000000000000000000000101101000101101000000000000101101000101101
  • 10011001010011001000000000010011001010011001000000000000000000000000000000000000010011001010011001000000000010011001010011001

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

इन नंबरों का वर्णन करने के लिए बेहतर शब्द के लिए बीटा का धन्यवाद।

अपडेट: काश ऐसा लगता है कि पैटर्न पर्याप्त रूप से शुरू होने पर टूट जाता है, जैसे कि शुरुआती पर्याप्त स्ट्रिंग, जैसे: 10000000000001:

100000000000011
10000000000001101
100000000000011011
10000000000001101100001
100000000000011011000011
10000000000001101100001101
100000000000011011000011010000000001
100000000000011011000011010000000001001
1000000000000110110000110100000000010011
1000000000000110110000110100000000010011001
10000000000001101100001101000000000100110010000000001
10000000000001101100001101000000000100110010000000001000001
1000000000000110110000110100000000010011001000000000100000100000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011
1000000000000110110000110100000000010011001000000000100000100000000000001101
100000000000011011000011010000000001001100100000000010000010000000000000110100001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011001000000000000000000000010010000010000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001001000000000000000000000000000000000000110010000000000000000000000100100000100000011
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001000001000000110000000000001

2
पवित्र * @ !!, ये सच हैं! यदि यह धारण करता है, तो यह 1 की संख्या पर एक ऊपरी सीमा रखता है, और यह O (n) से कम है।
बीटा

भग्न, यह उनका वर्णन करने के लिए एक बेहतर शब्द है। धन्यवाद
z -

दिलचस्प है, ये पैटर्न कैंटर के टर्नरी सेट ( en.wikipedia.org/wiki/Cantor_set ) से मिलते जुलते हैं । यदि ऐसा है, तो लोगों का अनुपात शून्य हो जाता है ...
flybywire

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

3
उनके समग्र आकार की तुलना में तारों में लोगों की संख्या का मेरा विश्लेषण यह प्रतीत करता है कि संख्या और स्ट्रिंग के आकार के बीच एक रैखिक संबंध है, जिससे मुझे विश्वास होता है कि कोई खुश ऊपरी सीमा नहीं है जो हमें यह कहने देती है कि एक स्ट्रिंग में लोगों की संख्या किसी दिए गए स्ट्रिंग के लिए अधिकांश लॉग (n) पर होगी। तो केवल लोगों की स्थिति से निपटने वाले समाधान और न ही पूरे स्ट्रिंग ओ (एन ^ 2) होने जा रहे हैं, भी। या, अधिक सटीक रूप से, O (n + m ^ 2), जहां m स्ट्रिंग में लोगों की संख्या है, और n स्ट्रिंग का आकार है, और m बड़ा-थीटा (n) है।
वेल्बोग

6

मुझे संदेह है कि O (n ^ 2) जैसा दिखने वाला एक सरल तरीका वास्तव में O (n ln (n)) की तरह कुछ बेहतर होगा। वे अनुक्रम जो परीक्षण के लिए सबसे लंबे समय तक लगते हैं (किसी भी n के लिए) वे होते हैं जिनमें कोई तिकड़ी नहीं होती है, और यह 1 की संख्या पर गंभीर प्रतिबंध लगाता है जो अनुक्रम में हो सकता है।

मैं कुछ हाथ से लहराते हुए तर्क के साथ आया हूं, लेकिन मैं एक स्पष्ट प्रमाण नहीं खोज पाया हूं। मैं अंधेरे में छुरा लेने जा रहा हूं: जवाब एक बहुत ही चतुर विचार है जिसे प्रोफेसर इतने लंबे समय से जानते हैं कि यह स्पष्ट प्रतीत होता है, लेकिन यह छात्रों के लिए बहुत कठिन है। (या तो वह या आप इसे कवर करने वाले व्याख्यान के माध्यम से सो गए।)


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

3

संशोधन: 2009-10-17 23:00

मैंने इसे बड़ी संख्या में चलाया है (जैसे, 20 मिलियन के तार) और मुझे अब विश्वास है कि यह एल्गोरिथ्म O (n logn) नहीं है। इसके बावजूद, यह एक अच्छा पर्याप्त कार्यान्वयन है और इसमें कई अनुकूलन शामिल हैं जो इसे वास्तव में तेजी से चलाते हैं। यह 25 सेकंड से कम समय में 24 या उससे कम अंकों के बाइनरी स्ट्रिंग्स की सभी व्यवस्थाओं का मूल्यांकन करता है।

मैंने 0 <= L < M < U <= X-1आज से पहले के अवलोकन को शामिल करने के लिए कोड अपडेट किया है।


मूल

यह अवधारणा में, एक अन्य प्रश्न के समान है जिसका मैंने उत्तर दिया था । यह कोड एक श्रृंखला में तीन मूल्यों को भी देखता है और निर्धारित करता है कि क्या एक ट्रिपल ने एक शर्त को संतुष्ट किया है। यहाँ C # कोड उस से अनुकूलित है:

using System;
using System.Collections.Generic;

namespace StackOverflow1560523
{
    class Program
    {
        public struct Pair<T>
        {
            public T Low, High;
        }
        static bool FindCandidate(int candidate, 
            List<int> arr, 
            List<int> pool, 
            Pair<int> pair, 
            ref int iterations)
        {
            int lower = pair.Low, upper = pair.High;
            while ((lower >= 0) && (upper < pool.Count))
            {
                int lowRange = candidate - arr[pool[lower]];
                int highRange = arr[pool[upper]] - candidate;
                iterations++;
                if (lowRange < highRange)
                    lower -= 1;
                else if (lowRange > highRange)
                    upper += 1;
                else
                    return true;
            }
            return false;
        }
        static List<int> BuildOnesArray(string s)
        {
            List<int> arr = new List<int>();
            for (int i = 0; i < s.Length; i++)
                if (s[i] == '1')
                    arr.Add(i);
            return arr;
        }
        static void BuildIndexes(List<int> arr, 
            ref List<int> even, ref List<int> odd, 
            ref List<Pair<int>> evenIndex, ref List<Pair<int>> oddIndex)
        {
            for (int i = 0; i < arr.Count; i++)
            {
                bool isEven = (arr[i] & 1) == 0;
                if (isEven)
                {
                    evenIndex.Add(new Pair<int> {Low=even.Count-1, High=even.Count+1});
                    oddIndex.Add(new Pair<int> {Low=odd.Count-1, High=odd.Count});
                    even.Add(i);
                }
                else
                {
                    oddIndex.Add(new Pair<int> {Low=odd.Count-1, High=odd.Count+1});
                    evenIndex.Add(new Pair<int> {Low=even.Count-1, High=even.Count});
                    odd.Add(i);
                }
            }
        }

        static int FindSpacedOnes(string s)
        {
            // List of indexes of 1s in the string
            List<int> arr = BuildOnesArray(s);
            //if (s.Length < 3)
            //    return 0;

            //  List of indexes to odd indexes in arr
            List<int> odd = new List<int>(), even = new List<int>();

            //  evenIndex has indexes into arr to bracket even numbers
            //  oddIndex has indexes into arr to bracket odd numbers
            List<Pair<int>> evenIndex = new List<Pair<int>>(), 
                oddIndex = new List<Pair<int>>(); 
            BuildIndexes(arr, 
                ref even, ref odd, 
                ref evenIndex, ref oddIndex);

            int iterations = 0;
            for (int i = 1; i < arr.Count-1; i++)
            {
                int target = arr[i];
                bool found = FindCandidate(target, arr, odd, oddIndex[i], ref iterations) || 
                    FindCandidate(target, arr, even, evenIndex[i], ref iterations);
                if (found)
                    return iterations;
            }
            return iterations;
        }
        static IEnumerable<string> PowerSet(int n)
        {
            for (long i = (1L << (n-1)); i < (1L << n); i++)
            {
                yield return Convert.ToString(i, 2).PadLeft(n, '0');
            }
        }
        static void Main(string[] args)
        {
            for (int i = 5; i < 64; i++)
            {
                int c = 0;
                string hardest_string = "";
                foreach (string s in PowerSet(i))
                {
                    int cost = find_spaced_ones(s);
                    if (cost > c)
                    {
                        hardest_string = s;
                        c = cost;
                        Console.Write("{0} {1} {2}\r", i, c, hardest_string);
                    }
                }
                Console.WriteLine("{0} {1} {2}", i, c, hardest_string);
            }
        }
    }
}

मुख्य अंतर हैं:

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

सामान्य विचार सूचकांक पर काम करना है, न कि डेटा का कच्चा प्रतिनिधित्व। एक ऐसी सरणी की गणना करना जहां 1 का प्रकट होना एल्गोरिदम को डेटा की लंबाई के आनुपातिक समय के बजाय डेटा में 1 की संख्या के लिए आनुपातिक रूप से चलाने की अनुमति देता है। यह एक मानक परिवर्तन है: एक डेटा संरचना बनाएं जो समस्या को समान रखते हुए तेजी से संचालन की अनुमति देता है।

परिणाम पुराने हैं: हटाए गए।


संपादित करें: 2009-10-16 18:48

Yx के डेटा पर, जिसे गणना करने के लिए कठिन डेटा के प्रतिनिधि के रूप में अन्य प्रतिक्रियाओं में कुछ विश्वसनीयता दी जाती है, मुझे ये परिणाम मिलते हैं ... इन्हें हटा दिया। वे पुराने हैं।

मैं यह बताना चाहूंगा कि यह डेटा मेरे एल्गोरिथम के लिए सबसे मुश्किल नहीं है, इसलिए मुझे लगता है कि यह धारणा कि yx के फ्रैक्टल्स को हल करना सबसे मुश्किल है, गलत है। एक विशेष एल्गोरिथ्म के लिए सबसे खराब स्थिति, मुझे उम्मीद है, एल्गोरिथ्म पर ही निर्भर करेगा और संभवतः अलग-अलग एल्गोरिदम के अनुरूप नहीं होगा।


संपादित करें: 2009-10-17 13:30

इस पर आगे की टिप्पणियां।

सबसे पहले, 1 की प्रत्येक स्थिति के लिए 0 और 1 के स्ट्रिंग को एक अनुक्रमित अनुक्रम में बदलें। उस सरणी की लंबाई कहो A, X है। फिर लक्ष्य को खोजना है

0 <= L < M < U <= X-1

ऐसा है कि

A[M] - A[L] = A[U] - A[M]

या

2*A[M] = A[L] + A[U]

चूंकि A [L] और A [U] एक सम संख्या में हैं, वे (सम, विषम) या (विषम, सम) नहीं हो सकते। एक मैच की खोज को ए [] को विषम और यहां तक ​​कि पूल में विभाजित करके और विषम में और यहां तक ​​कि उम्मीदवारों के पूल में ए [एम] पर मैचों की खोज करके बेहतर बनाया जा सकता है।

हालाँकि, यह एक एल्गोरिथम सुधार की तुलना में प्रदर्शन अनुकूलन का अधिक है, मुझे लगता है। तुलना की संख्या गिरनी चाहिए, लेकिन एल्गोरिथ्म का क्रम समान होना चाहिए।


संपादित करें 2009-10-18 00:45

फिर भी एक और अनुकूलन मेरे लिए होता है, एक ही नस में उम्मीदवारों को समान और विषम में अलग करना। चूँकि तीनों इंडेक्स को 3 (a, a + x, a + 2x - mod 3 को 0, a और x की परवाह किए बिना) में जोड़ना होता है, आप L, M और U को उनके मॉड 3 मानों में अलग कर सकते हैं। :

M  L  U
0  0  0
   1  2
   2  1
1  0  2
   1  1
   2  0
2  0  1
   1  0
   2  2

वास्तव में, आप इसे सम-विषम अवलोकन के साथ जोड़ सकते हैं और उन्हें उनके मॉड 6 मानों में अलग कर सकते हैं:

M  L  U
0  0  0
   1  5
   2  4
   3  3
   4  2
   5  1

और इसी तरह। यह एक और प्रदर्शन अनुकूलन प्रदान करेगा लेकिन एक एल्गोरिथम गति नहीं।


2

अभी तक समाधान के साथ आने में सक्षम नहीं था :(, लेकिन कुछ विचार हैं।

क्या होगा अगर हम एक रिवर्स समस्या से शुरू करते हैं: 1s की अधिकतम संख्या के साथ एक अनुक्रम का निर्माण करें और बिना किसी समान दूरी के त्रिकोणीय के बिना। यदि आप साबित कर सकते हैं कि 1s की अधिकतम संख्या o (n) है, तो आप केवल 1s की सूची के माध्यम से पुनरावृति करके अपने अनुमान में सुधार कर सकते हैं।


खैर, 1 की संख्या निश्चित रूप से O (n) से ऊपर है। यह O (n ** 2) नहीं हो सकता, सही है - 1 की संख्या डेटा की तुलना में तेज़ी से बढ़ती है? महत्वपूर्ण सवाल यह है कि क्या ऊपरी सीमा इससे कम है।
२१:१० बजे हुग्डब्रोर्न

मैंने छोटे ओ का इस्तेमाल किया, बड़े वाले का नहीं
ओलेक्सि

2

यह मदद कर सकता है ....

यह समस्या निम्न को कम करती है:

सकारात्मक पूर्णांकों के अनुक्रम को देखते हुए, उपसर्ग और प्रत्यय में विभाजित एक सन्निहित अनुवर्ती खोजें, जैसे कि उपसर्ग के उपसर्ग का योग परिणाम के प्रत्यय के योग के बराबर है।

उदाहरण के लिए, के एक क्रम को देखते हुए [ 3, 5, 1, 3, 6, 5, 2, 2, 3, 5, 6, 4 ], हम [ 3, 6, 5, 2, 2]उपसर्ग के [ 3, 6 ]साथ एक उपसर्ग और उपसर्ग योग के साथ 9और प्रत्यय की [ 5, 2, 2 ]राशि के साथ एक प्रत्यय पाएंगे 9

कटौती निम्नानुसार है:

शून्य और अपनों के अनुक्रम को देखते हुए, और सबसे बाईं ओर शुरू करके, दाईं ओर बढ़ना जारी रखें। हर बार एक दूसरे का सामना किया जाता है, पिछले एक के बाद से चालों की संख्या रिकॉर्ड की गई थी और उस नंबर को परिणामी अनुक्रम में जोड़ दिया।

उदाहरण के लिए, के एक क्रम को देखते हुए [ 0, 1, 1, 0, 0, 1, 0, 0, 0, 1 0 ], हम कमी को खोज लेंगे [ 1, 3, 4]। इस कमी से, हम योग के [ 1, 3, 4]उपसर्ग और बाद के [ 1, 3]योग के 4प्रत्यय की गणना करते [ 4 ]हैं 4

इस कमी की गणना की जा सकती है O(n)

दुर्भाग्य से, मुझे यकीन नहीं है कि यहाँ से कहाँ जाना है।


1
यह अधिक कॉम्पैक्ट नोटेशन है, लेकिन यह समय जटिलता में मदद नहीं करेगा। "उपसर्ग" विभाजन का सेट "1" की सभी घटनाओं में एक-जोड़े की खोज के लिए आइसोमोर्फिक है, जो ओ (एन ^ 2) है।
p00ya

जाहिरा तौर पर वहाँ एल्गोरिदम वहाँ सन्निहित बाद sums के साथ काम कर रहे हैं। दुर्भाग्य से वे सभी O (n) में अधिकतम राशि के साथ सन्निहित परिणाम को खोजने के लिए व्यवहार करते हैं।
yfeldblum

@ p00ya यह सही नहीं है। इस अल्गोरिट्म के समय का उपयोग करने से सह-अस्तित्व झूठे लोगों की संख्या की ऊपरी सीमा पर निर्भर करता है, जो कैंटर द्वारा निर्मित स्ट्रिंग पर (3/2) ^ (लॉग (n) / लॉग (3)) और स्पेस कॉम्प्लेक्स बन जाता है। लेकिन समय जटिलता n द्वारा इस गुणा हो जाती है। मेरा दूसरा उत्तर जांचें। (नकारात्मक नहीं): डी
लुका रहाने

@ralu: यह आपकी धारणा के तहत है कि कैंटर जनित तार सबसे खराब स्थिति में हैं, जो गलत है। रिकॉर्ड के लिए, जोड़े की संख्या निश्चित रूप से हे (n ^ 2) है; लेकिन मुझे लगता है कि मैं वास्तव में लग रहा था कि यह बड़ा-ओमेगा (एन ^ 2) था, जो गलत है ये परिणाम दिए गए हैं (विशेष रूप से नारोटन लिंक देखें), बड़े-ओमेगा (n ^ (2 / 1.52) के जोड़े में एक कम बाध्यता का सुझाव देते हैं। )) प्रमाण या बड़े-ओमेगा (n ^ (4/3)) द्वारा अनुमान द्वारा।
p00ya

1

साधारण समस्या के प्रकार के लिए (यानी आप तीन "1" को केवल (यानी शून्य या अधिक) "0" के बीच में खोजते हैं ), इसका बिल्कुल सरल: आप बस हर "1" पर अनुक्रम को विभाजित कर सकते हैं और दो आसन्न बाद वाले को देख सकते हैं। एक ही लंबाई (दूसरी अंतिमता निश्चित रूप से अंतिम नहीं है)। जाहिर है, यह ओ (एन) समय में किया जा सकता है ।

अधिक जटिल संस्करण के लिए (जैसे कि आप एक इंडेक्स i और एक अंतर g > 0 ऐसे खोजते हैं s[i]==s[i+g]==s[i+2*g]=="1"), मुझे यकीन नहीं है, अगर कोई O (n लॉग एन) समाधान मौजूद है, क्योंकि संभवतः O (n²) ट्रिपल वाले हैं यह संपत्ति (सभी लोगों के लिए एक स्ट्रिंग के बारे में सोचो, वहाँ लगभग n 2/2 ऐसे ट्रिपल हैं)। बेशक, आप इनमें से केवल एक की तलाश कर रहे हैं, लेकिन मुझे वर्तमान में कोई पता नहीं है, इसे कैसे खोजना है ...


हां, हम समस्या के कठिन संस्करण पर चर्चा कर रहे हैं। फिर भी, n * log (n) समाधान संभव हो सकता है।
ओलेक्सि

1
वास्तव में n 3 चुनें जो O (n ^ 3) संभव त्रिभुज हैं, मुझे लगता है कि जब आपने लगभग n ^
2/2

@gmatt: n चूज 2 पर्याप्त है; अगर हम दो 1s को ठीक करते हैं तो तीसरे की स्थिति निर्धारित होती है और यह देखने के लिए निरंतर समय है कि क्या उस स्थिति में 1 है या नहीं।
श्रीवत्सआर

@ श्रीवत्स: हाँ ठीक है, मुझे लगता है, मैं अनर्गल मामले के बारे में सोच रहा था।
ldog

1
@gmatt: वास्तव में, हम Tuples (i, g) की तलाश कर रहे हैं, जैसा कि ऊपर बताई गई बाधाओं के साथ है कि 0 <= i <(n-3) और 0 <g <(ni-1) / 2, इसलिए A का अनुमान n ^
2/2

1

एक मजेदार सवाल, लेकिन एक बार जब आपको पता चलता है कि दो '1' के बीच वास्तविक पैटर्न कोई फर्क नहीं पड़ता है, तो एल्गोरिथ्म बन जाता है:

  • '1' के लिए स्कैन देखो
  • किसी अन्य '1' के लिए अगली स्थिति के स्कैन से शुरू (सरणी के अंत तक शून्य से वर्तमान पहले '1' की दूरी या फिर तीसरे '1' की सीमा समाप्त हो जाएगी)
  • अगर 2 '1' प्लस की स्थिति में पहले 1 'तीसरे' 1 'की दूरी पाई जाती है, तो हमारे पास समान रूप से रिक्त स्थान हैं।

कोड में, JTest फैशन, (ध्यान दें कि यह कोड सबसे अधिक कुशल नहीं लिखा गया है और मैंने यह देखने के लिए कुछ प्रिंटलाइन जोड़ी है कि क्या होता है।)

import java.util.Random;

import junit.framework.TestCase;

public class AlgorithmTest extends TestCase {

 /**
  * Constructor for GetNumberTest.
  *
  * @param name The test's name.
  */
 public AlgorithmTest(String name) {
  super(name);
 }

 /**
  * @see TestCase#setUp()
  */
 protected void setUp() throws Exception {
  super.setUp();
 }

 /**
  * @see TestCase#tearDown()
  */
 protected void tearDown() throws Exception {
  super.tearDown();
 }

 /**
  * Tests the algorithm.
  */
 public void testEvenlySpacedOnes() {

  assertFalse(isEvenlySpaced(1));
  assertFalse(isEvenlySpaced(0x058003));
  assertTrue(isEvenlySpaced(0x07001));
  assertTrue(isEvenlySpaced(0x01007));
  assertTrue(isEvenlySpaced(0x101010));

  // some fun tests
  Random random = new Random();

  isEvenlySpaced(random.nextLong());
  isEvenlySpaced(random.nextLong());
  isEvenlySpaced(random.nextLong());
 }

 /**
  * @param testBits
  */
 private boolean isEvenlySpaced(long testBits) {
  String testString = Long.toBinaryString(testBits);
  char[] ones = testString.toCharArray();
  final char ONE = '1';

  for (int n = 0; n < ones.length - 1; n++) {

   if (ONE == ones[n]) {
    for (int m = n + 1; m < ones.length - m + n; m++) {

     if (ONE == ones[m] && ONE == ones[m + m - n]) {
      System.out.println(" IS evenly spaced: " + testBits + '=' + testString);
      System.out.println("               at: " + n + ", " + m + ", " + (m + m - n));
      return true;
     }
    }
   }
  }

  System.out.println("NOT evenly spaced: " + testBits + '=' + testString);
  return false;
 }
}

4
यदि मैं गलत नहीं हूँ, तो यह O (n not) है क्योंकि बाहरी लूप n बार और आंतरिक लूप औसतन n / 2 बार चलता है।
स्ट्रिपिंगवर्यर

बाहरी लूप n बार और आंतरिक लूप औसत रूप से n / 4 चलाता है, लेकिन केवल एक '1' के बाद वाले पदों से शुरू होता है। N ^ 2 व्यवहार के लिए '1' की संख्या अधिक होनी चाहिए, जिसके परिणामस्वरूप सही परिणाम प्राप्त होता है जिससे प्रसंस्करण बंद हो जाता है। इसलिए n ^ 2 व्यवहार कभी नहीं होगा। डेटा के ज्ञात गुणों के आधार पर O को कैसे निर्धारित किया जाए, इस समय मुझे बच जाता है।
19

दुर्भाग्य से यह औसत वास्तविक जीवन क्रम के बारे में नहीं है, बल्कि सैद्धांतिक रूप से बिग ओ रनटाइम है। और आपका दृष्टिकोण O (n²) है (मेरा जैसा है क्योंकि आपका दृष्टिकोण भी मेरा ही है)
DaClown

मैं औसत व्यवहार के बारे में बात नहीं कर रहा था, लेकिन अधिकतम व्यवहार। मुझे आश्चर्य नहीं होगा अगर यह साबित हो जाए कि परीक्षण में विफल होने वाली अधिकतम एन्ट्रापी में लॉग एन '1' स्ट्रिंग में है।
आरपी

क्या होगा यदि आप आंतरिक लूप में पाए गए पहले 1 के साथ बाहरी लूप में सूचकांक को अपडेट करते हैं, अर्थात (यदि [m] == एक) {n = m}? क्या यह बड़े ओ की मदद करता है?
स्टीमर २५

1

मैंने सोचा कि काम कर सकता हूँ एक विभाजित और जीत दृष्टिकोण।

सबसे पहले, प्रीप्रोसेसिंग में आपको एक सूची में अपने इनपुट आकार ( एन / 3) से आधे से कम सभी संख्याओं को सम्मिलित करने की आवश्यकता होती है ।

एक स्ट्रिंग दी: 0000010101000100(ध्यान दें कि यह विशेष उदाहरण मान्य है)

1 से (16/2) सभी सूची (1) से एक सूची में डालें: {1, 2, 3, 4, 5, 6, 7}

फिर इसे आधे में विभाजित करें:

100000101 01000100

ऐसा तब तक करते रहें जब तक आपको आकार के तार न मिलें 1. सभी आकार-एक के साथ एक तार के साथ उनमें से 1, स्ट्रिंग की अनुक्रमणिका को संभावनाओं की सूची में जोड़ें; अन्यथा, विफलता के लिए -1 लौटें।

आपको प्रत्येक संभावित अनुक्रमणिका के साथ संबद्ध रिक्त स्थान की सूची वापस करने की आवश्यकता होगी। (ऊपर दी गई सूची से शुरू करें और जाते ही नंबर हटा दें) यहाँ, एक खाली सूची का मतलब है कि आप केवल 1 से काम कर रहे हैं और इसलिए इस बिंदु पर कोई भी रिक्ति संभव है; अन्यथा सूची में ऐसे स्थान शामिल हैं जिन्हें खारिज किया जाना चाहिए।

तो ऊपर दिए गए उदाहरण के साथ जारी है:

1000 0101 0100 0100

10 00 01 01 01 00 01 00

1 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0

पहले गठबंधन चरण में, हमारे पास अब दो के आठ सेट हैं। पहले में, हमारे पास एक सेट की संभावना है, लेकिन हम सीखते हैं कि 1 द्वारा रिक्ति असंभव है क्योंकि अन्य शून्य वहां है। इसलिए हम 0 (इंडेक्स के लिए) और {2,3,4,5,7} इस तथ्य के लिए लौटते हैं कि 1 से रिक्ति असंभव है। दूसरे में, हमारे पास कुछ भी नहीं है और इसलिए -1 वापसी करते हैं। तीसरे में हमारा कोई ऐसा मैच है जिसमें कोई भी स्पैकिंग 5 इंडेक्स में समाप्त नहीं हुई है, इसलिए 5, {1,2,3,4,5,7} वापस करें। चौथी जोड़ी में हम 7, {1,2,3,4,5,7} लौटते हैं। पांचवें में, 9 लौटें, {1,2,3,4,5,7}। छठे में, वापसी -1। सातवें में, वापसी 13, {1,2,3,4,5,7}। आठवें में, वापसी -1।

चार के चार सेटों में फिर से संयोजन, हमारे पास है:

1000: रिटर्न (0, {4,5,6,7}) 0101: रिटर्न (5, {2,3,4,5,6,7})), (7, {1,2,3,4,5,6 , 7}) 0100: रिटर्न (9, {3,4,5,6,7}) 0100: रिटर्न (13, {3,4,5,6,7})

आठ के सेट में संयोजन:

10000101: रिटर्न (0, {5,7}), (5, {2,3,4,5,6,7}}), (7, {1,2,3,4,5,6,7}) 01000100: वापसी (9, {4,7}), (13, {3,4,5,6,7})

सोलह के सेट में संयोजन:

10000101 01000100

जैसे-जैसे हम आगे बढ़ रहे हैं, हम अभी तक सभी संभावनाओं की जाँच करते रहते हैं। इस चरण तक हमने सामान छोड़ दिया है जो स्ट्रिंग के अंत से आगे निकल गया है, लेकिन अब हम सभी संभावनाओं की जांच कर सकते हैं।

मूल रूप से, हम पहले 1 को 5 और 7 की स्पेसिंग के साथ जांचते हैं, और पाते हैं कि वे 1 तक नहीं हैं। (ध्यान दें कि प्रत्येक चेक कंसिस्टेंट है, रैखिक समय नहीं है) फिर हम 2, 3, 4, 5, 6 और 7-- या की स्पैकिंग के साथ दूसरे एक (इंडेक्स 5) की जांच करते हैं, या हम करेंगे, लेकिन हम 2 पर रोक सकते हैं यह वास्तव में मेल खाता है।

ओह! यह एक लंबा एल्गोरिथ्म है।

मैं 100% नहीं जानता अगर यह अंतिम चरण के कारण ओ (एन लॉग एन) है , लेकिन जहां तक ​​मैं बता सकता हूं वहां सब कुछ निश्चित रूप से ओ (एन लॉग एन) है । मैं इसे बाद में वापस लाऊंगा और अंतिम चरण को परिष्कृत करने का प्रयास करूंगा।

EDIT: वेलबॉग की टिप्पणी को प्रतिबिंबित करने के लिए मेरे जवाब को बदल दिया। त्रुटि के लिए क्षमा करें। मैं बाद में कुछ छद्मकोड लिखूँगा, जब मुझे फिर से लिखने के लिए थोड़ा और समय मिलेगा। ;-)


मैं आपके एल्गोरिथ्म का पालन नहीं करता हूं, लेकिन एक एल्गोरिथ्म की कोशिश करने के लिए +1 जो वास्तव में O होने की कोशिश करता है (n log n)
ldog

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

आप केवल अपराधों की अंतराल संभावनाओं को क्यों देख रहे हैं? आप स्ट्रिंग का मिलान कैसे करना चाहेंगे 100010001? अगर मैं आपके दृष्टिकोण को सही ढंग से समझ पाऊं, तो वह इसका मिलान नहीं कर पाएगा क्योंकि सही उत्तर (0,{4})की गणना संभव नहीं है। यह देखते हुए कि आपको अपनी सूची में गैर-अपराधों की आवश्यकता है, पैथोलॉजिकल स्ट्रिंग्स के साथ आना आसान है जो संभावनाओं की सूची को बढ़ाता है जिन्हें आपको O (n लॉग (n)) से अधिक जांचने की आवश्यकता है, मुझे लगता है।
वेल्बोग

कसम खाता हूँ, मैं मूल रूप से कई गुना करने जा रहा था, लेकिन मैंने अपने उत्तर को बीच में बदल दिया और सब कुछ बदलने के लिए तैयार नहीं हुआ। माफ़ करना। जल्द ही ठीक हो जाएगा
प्लैटिनम एज़्योर

3
मुझे नहीं लगता कि यह ओ (एन लॉग एन) है। पहले गठबंधन चरण में, आप (n / 2) सेट का इलाज करते हैं, जिनमें से प्रत्येक संभवत: O (n) संभावित स्पेसिंग का एक सेट लौटाता है। यह अकेला इसे O (n ^ 2) बनाता है, दुर्भाग्य से।
मार्टिनस्टाइनर

1

मैं अपना मोटा अनुमान यहाँ दूंगा, और जो लोग मेरी एल्गोरिथ्म को ओ-नोटिफ़िक वार में किराए पर लेने में मेरी मदद करने की जटिलता के साथ बेहतर हैं उन्हें जाने दें

  1. दिया गया बाइनरी स्ट्रिंग 0000010101000100 (उदाहरण के लिए)
  2. जीरो की फसल का सिर और पूंछ -> 00000 101010001 00
  3. हमें पिछली गणना से 101010001 मिलता है
  4. जांचें कि क्या मध्य बिट 'एक' है, यदि सही है, तो वैध तीन समान रूप से '' पाए गए '' (केवल अगर बिट्स की संख्या विषम संख्या है)
  5. सहसंबद्ध रूप से, यदि बिट्स की क्रॉप संख्या भी समान है, तो सिर और पूंछ 'एक' समान रूप से 'एक' का हिस्सा नहीं हो सकते,
  6. हम उदाहरण के रूप में 1010100001 का उपयोग करते हैं (एक अतिरिक्त 'शून्य' के साथ भी गिने फसल हो जाते हैं), इस मामले में हमें फिर से फसल की जरूरत है, फिर बन जाता है -> 10101 00001
  7. हम पिछली गणना से 10101 प्राप्त करते हैं, और मध्य बिट की जांच करते हैं, और हमें समान रूप से फिर से बिट मिला

मुझे नहीं पता कि इसके लिए जटिलता की गणना कैसे की जाए, क्या कोई मदद कर सकता है?

संपादित करें: मेरे विचार को स्पष्ट करने के लिए कुछ कोड जोड़ें

edit2: मेरे कोड को संकलित करने की कोशिश की और कुछ बड़ी गलतियाँ पाईं, जिन्हें ठीक किया गया

char *binaryStr = "0000010101000100";

int main() {
   int head, tail, pos;
   head = 0;
   tail = strlen(binaryStr)-1;
   if( (pos = find3even(head, tail)) >=0 )
      printf("found it at position %d\n", pos);
   return 0;
}

int find3even(int head, int tail) {
   int pos = 0;
   if(head >= tail) return -1;
   while(binaryStr[head] == '0') 
      if(head<tail) head++;
   while(binaryStr[tail] == '0') 
      if(head<tail) tail--;
   if(head >= tail) return -1;
   if( (tail-head)%2 == 0 && //true if odd numbered
       (binaryStr[head + (tail-head)/2] == '1') ) { 
         return head;
   }else {
      if( (pos = find3even(head, tail-1)) >=0 )
         return pos;
      if( (pos = find3even(head+1, tail)) >=0 )
         return pos;
   }
   return -1;
}

@recursive मुझे लगता है कि यह तब काम करेगा जब यह कॉल find3even (हेड + 1, टेल) तक पहुंच जाएगी, जो फिर इसे 111 = 4 के सिर पर फसल देगा, क्या आप मेरे लिए फिर से जांच कर सकते हैं?
andycjw

@recursive कृपया मेरे द्वारा पहले बनाए गए छद्म कोड को बेहतर ढंग से समझाने के लिए मैंने जो कोड जोड़ा है, उसकी जांच करें, जो बहुत सख्त और संक्षिप्त नहीं है
andycjw

यह nlogn है - n बिट्स के लिए हम उम्मीद करते हैं कि लगभग logn पुनरावृत्तियों की जाँच n * c बिट्स जहां C एक स्थिर है।
रॉन वारहोलिक

हाँ, यह सबसे सरल मामलों के रूप में 111001 और 100111 पर विफल होता है। समान रूप से दूरी 1 को मध्य बिट पर केन्द्रित नहीं करना है।
डीन जे

यह उन मामलों को सही ढंग से संभालता है, 111001 में बिट्स की एक समान संख्या होती है इसलिए इसे तुरंत 111 और 001 में विभाजित किया जाता है। 111 के बाद से बिट्स की एक विषम संख्या होती है और मध्य बिट एक है जो इसे सफलतापूर्वक लौटाता है।
रॉन वारहोलिक

1

मैं कुछ इस तरह से आया:

def IsSymetric(number):
    number = number.strip('0')

    if len(number) < 3:
        return False
    if len(number) % 2 == 0:
        return IsSymetric(number[1:]) or IsSymetric(number[0:len(number)-2])
    else:
        if number[len(number)//2] == '1':
            return True
        return IsSymetric(number[:(len(number)//2)]) or IsSymetric(number[len(number)//2+1:])
    return False

यह andycjw से प्रेरित है।

  1. शून्य को काटें।
  2. यदि फिर भी दो सबस्ट्रिंग 0 का परीक्षण करें - (len-2) (अंतिम वर्ण को छोड़ें) और 1 से - (len-1) (पहले वर्ण को छोड़ें)
  3. अगर हम बीच में से एक भी ऐसा नहीं है, जिसमें हमें सफलता मिले। एल्स को मिडल एलिमेंट के बिना मिडल में स्ट्रिंग को विभाजित करें और दोनों हिस्सों को चेक करें।

जटिलता के रूप में यह O (nlogn) हो सकता है क्योंकि प्रत्येक पुनरावृत्ति में हम दो से विभाजित कर रहे हैं।

आशा करता हूँ की ये काम करेगा।


ऐसा लगता है कि आप N तत्वों के साथ समस्या को N-1 तत्वों के साथ 2 समस्याओं में परिवर्तित कर रहे हैं। इसे आधे में विभाजित करने का मतलब होगा कि इसे एन / 2 तत्वों के साथ 2 समस्याओं में बदलना।
RHSeeger

यह केवल लंबाई के लिए भी मामला है। तो अगर लेन 8 है एल्गोरिथ्म लंबाई के तार बनाता है: 7, 7, 3, 3, 3, 3. पुनरावृत्ति पेड़ की ऊँचाई 3 है और यह lg (8) के बराबर है।
बेकु

1

ठीक है, मैं समस्या पर एक और छुरा लेने जा रहा हूं। मुझे लगता है कि मैं एक ओ (एन लॉग (एन)) एल्गोरिथ्म को साबित कर सकता हूं जो 1 के बीच की दूरी को स्टोर करने के लिए एक संतुलित बाइनरी ट्री का उपयोग करके पहले से ही चर्चा किए गए समान है। यह दृष्टिकोण न्यायमूर्ति द्वारा 1 के बीच की दूरी की सूची में समस्या को कम करने के बारे में अवलोकन से प्रेरित था।

क्या हम 1 की स्थिति के आसपास संतुलित बाइनरी ट्री बनाने के लिए इनपुट स्ट्रिंग को स्कैन कर सकते हैं, जैसे कि प्रत्येक नोड 1 की स्थिति को संग्रहीत करता है और प्रत्येक किनारे को प्रत्येक बच्चे के नोड के लिए दूरी 1 के साथ लेबल किया जाता है। उदाहरण के लिए:

10010001 gives the following tree

      3
     / \
  2 /   \ 3
   /     \
  0       7

यह O (n लॉग (n)) में किया जा सकता है, क्योंकि आकार n की एक स्ट्रिंग के लिए, प्रत्येक प्रविष्टि सबसे खराब स्थिति में O (लॉग (n)) लेता है।

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

क्या मैं कुछ भूल गया?


"चूँकि सबट्री में पथों की संख्या लॉग (n) के समानुपाती होगी" क्यों नहीं n? आम तौर पर यह एक आशाजनक दृष्टिकोण है।
sdcvvc

@ sdcwc: यह लॉग (n) और n नहीं के अनुपात में है क्योंकि एक संतुलित पेड़ में प्रत्येक उपश्रेणी में आधे नोड्स होते हैं, और सबट्री के रूट के रास्तों की संख्या सबट्री में नोड्स की संख्या के समान होती है (को छोड़कर) रूट)।
जेरेमी बॉर्क

0

यह एक मजेदार समस्या थी, इसलिए मैंने इस पर अपना हाथ आजमाने का फैसला किया।

मैं यह धारणा बना रहा हूं कि 111000001 पहले 3 लोगों को ढूंढेगा और सफल होगा। 1 के बाद अनिवार्य रूप से शून्य की संख्या महत्वपूर्ण बात है, क्योंकि 0111000 आपकी परिभाषा के अनुसार 111000 के समान है। एक बार जब आप 1 के दो मामले पाते हैं, तो अगले 1 को त्रयी पूर्ण होती है।

यहाँ यह पायथन में है:

def find_three(bstring):
    print bstring
    dict = {}
    lastone = -1
    zerocount = 0
    for i in range(len(bstring)):
        if bstring[i] == '1':
            print i, ': 1'
            if lastone != -1:
                if(zerocount in dict):
                    dict[zerocount].append(lastone)
                    if len(dict[zerocount]) == 2:
                        dict[zerocount].append(i)
                        return True, dict
                else:
                    dict[zerocount] = [lastone]
            lastone = i
            zerocount = 0
        else:
            zerocount = zerocount + 1
    #this is really just book keeping, as we have failed at this point
    if lastone != -1:
        if(zerocount in dict):
            dict[zerocount].append(lastone)
        else:
            dict[zerocount] = [lastone]
    return False, dict

यह एक पहला प्रयास है, इसलिए मुझे यकीन है कि यह एक क्लीनर तरीके से लिखा जा सकता है। कृपया उन मामलों को सूचीबद्ध करें जहां यह विधि नीचे विफल रहती है।


@ संक्षिप्त, वे समान रूप से स्थान नहीं हैं।
जेम्स मैकमोहन

क्या आप समान रूप से दूरी से मतलब है? इंडेक्स 0, 3 और 6 को देखें। सभी, और प्रत्येक को दो अलग करने के साथ।
पुनरावर्ती

ओह, मैं देख रहा हूँ, जैसा कि मैंने इसे समझा, शून्य केवल रिक्ति में शामिल थे।
जेम्स मैकमोहन

प्रश्न "1001011" का उल्लेख करता है, जिस पर यह काम नहीं करता है। प्रश्न पूछे जाने के तुरंत बाद पोस्ट किया गया एक (अब हटा दिया गया) उत्तर था, जिसने इस (उसी) समस्या को हल कर दिया। :-)
श्रीवत्सआर

मैं आज इस काम को देख रहा था और मुझे समझ नहीं आ रहा था कि रॉब को अपने संपादन से क्या मतलब है। मैंने स्पष्टता के लिए प्रश्न संपादित किया है। मुझे पता होना चाहिए कि मुझे कुछ याद आ रहा था जब मेरे पास एक आसान समय था।
जेम्स मैकमोहन

0

मुझे लगता है कि यह कारण है nlog (n) निम्नलिखित के कारण है:

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

तो, आपके पास n, लॉग (n), और 1 ... O (nlogn) है

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


Tcl में कार्यान्वयन

proc get-triplet {input} {
    for {set first 0} {$first < [string length $input]-2} {incr first} {
        if {[string index $input $first] != 1} {
            continue
        }
        set start [expr {$first + 1}]
        set end [expr {1+ $first + (([string length $input] - $first) /2)}]
        for {set second $start} {$second < $end} {incr second} {
            if {[string index $input $second] != 1} {
                continue
            }
            set last [expr {($second - $first) + $second}]
            if {[string index $input $last] == 1} {
                return [list $first $second $last]
            }
        }
    }
    return {}
}

get-triplet 10101      ;# 0 2 4
get-triplet 10111      ;# 0 2 4
get-triplet 11100000   ;# 0 1 2
get-triplet 0100100100 ;# 1 4 7

0

मुझे लगता है कि मुझे समस्या को हल करने का एक तरीका मिल गया है, लेकिन मैं एक औपचारिक सबूत का निर्माण नहीं कर सकता। मेरे द्वारा बनाया गया समाधान जावा में लिखा गया है, और यह गिनने के लिए काउंटर 'एन' का उपयोग करता है कि यह कितनी सूची / सरणी का उपयोग करता है। यदि यह सही है तो n, स्ट्रिंग स्ट्रेंथ * लॉग (स्ट्रिंगलॉग्रफ़) से कम या बराबर होना चाहिए। मैंने इसे 0 से 2 ^ 22 की संख्या के लिए आज़माया, और यह काम करता है।

यह इनपुट स्ट्रिंग पर पुनरावृत्ति करके और सभी इंडेक्स की सूची बनाकर शुरू होता है जो किसी एक को पकड़ते हैं। यह सिर्फ O (n) है।

फिर इंडेक्स की सूची से यह एक फ़र्स्टइंडेक्स, और एक सेकंडइंडेक्स चुनता है जो पहले से अधिक है। इन दो अनुक्रमितों को पकड़ना आवश्यक है, क्योंकि वे सूचकांक की सूची में हैं। वहां से थर्डइंडेक्स की गणना की जा सकती है। यदि inputString [thirdIndex] 1 है तो यह रुक जाता है।

public static int testString(String input){
//n is the number of array/list accesses in the algorithm
int n=0;

//Put the indices of all the ones into a list, O(n)
ArrayList<Integer> ones = new ArrayList<Integer>();
for(int i=0;i<input.length();i++){
    if(input.charAt(i)=='1'){
        ones.add(i);
    }
}

//If less than three ones in list, just stop
if(ones.size()<3){
    return n;
}

int firstIndex, secondIndex, thirdIndex;
for(int x=0;x<ones.size()-2;x++){
    n++;
    firstIndex = ones.get(x);

    for(int y=x+1; y<ones.size()-1; y++){
        n++;
        secondIndex = ones.get(y);
        thirdIndex = secondIndex*2 - firstIndex;

        if(thirdIndex >= input.length()){
            break;
        }

        n++;
        if(input.charAt(thirdIndex) == '1'){
            //This case is satisfied if it has found three evenly spaced ones
            //System.out.println("This one => " + input);
            return n;
        }
    }
}

return n;

}

अतिरिक्त नोट: जब इंडेक्स की सूची बनाने के लिए इनपुट स्ट्रिंग पर पुनरावृति होती है, तो काउंटर एन को इंक्रीमेंट नहीं किया जाता है। यह ऑपरेशन O (n) है, इसलिए इसका एल्गोरिदम की जटिलता पर कोई प्रभाव नहीं पड़ेगा।


आप अभी भी O (n) के दो छोरों को देखते हैं, नेस्टेड, जो इसे O (n ^ 2) बनाता है
RHSeeger

अनुक्रमणिका की सरणी इनपुट स्ट्रिंग के समान आकार नहीं है। यह मेरे लिए एक वास्तविक प्रमाण लिखना मुश्किल है या यह साबित करना गलत है। मुझे संदेह है कि कुछ अंतर्निहित गणितीय विचार है जो यह काम करता है।
राबर्ट पार्कर

1
मुझे लगता है कि इस समस्या की चाल यह है कि आपके एल्गोरिथ्म O (n ^ 2) होने के बावजूद, एक स्ट्रिंग का सबसे खराब संभव मामला आपको केवल O (nlogn) पुनरावृत्तियों में परिणाम देगा अन्यथा आपको अपने एल्गोरिथ्म का उपयोग करके समाधान मिल जाएगा।
z -

2
2 ^ 22 तक इसका परीक्षण वास्तव में यह जटिलता नहीं है का परीक्षण करता है। 2 ^ 22 में केवल 22 बिट्स हैं, जिसका अर्थ है कि आपका N 22 है। कुछ मानों के लिए प्रयास करें जहां N कुछ मिलियन है।
पीटर रेकोर

1
इस एल्गोरिथ्म को yx के उत्तर में दिए गए अधिकतम "खराब" तारों के साथ आज़माएँ और आप पाएंगे कि यह एक O(n^2)एल्गोरिथम है।
वेल्बोग

0

इस समस्या में एक कारक और स्थानांतरण के बारे में सोचना है।

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

1010101010
  1010101010
------------
001010101000

परिणामी 1 (बिटवाइड एंडेड) को उन सभी 1 का प्रतिनिधित्व करना चाहिए जो समान रूप से दो द्वारा दिए गए हैं। तीन द्वारा स्थानांतरित एक ही उदाहरण:

1010101010
   1010101010
-------------
0000000000000

इस मामले में 1 नहीं हैं जो समान रूप से तीन अलग-अलग हैं।

तो यह आपको क्या बताता है? ठीक है कि आपको केवल उन पारियों का परीक्षण करना होगा जो अभाज्य संख्याएँ हैं। उदाहरण के लिए, आपके पास दो 1 हैं जो छह अलग हैं। आपको केवल 'दो ’पारियों और sh तीन’ पारियों का परीक्षण करना होगा (क्योंकि ये छह विभाजित हैं)। उदाहरण के लिए:

10000010 
  10000010 (Shift by two)
    10000010
      10000010 (We have a match)

10000010
   10000010 (Shift by three)
      10000010 (We have a match)

तो केवल पारियों की आपको कभी-कभी 2,3,5,7,11,13 आदि की जांच करने की आवश्यकता होती है, अंकों के स्ट्रिंग के आकार के वर्गमूल के सबसे निकटतम।

लगभग हल?

मुझे लगता है कि मैं एक समाधान के करीब हूं। मूल रूप से:

  1. 1 के लिए स्ट्रिंग को स्कैन करें। प्रत्येक 1 नोट के लिए यह अपनी स्थिति के मापांक लेने के बाद शेष है। मापांक स्ट्रिंग के 1 से आधे आकार तक होता है। इसका कारण यह है कि सबसे बड़ा संभव पृथक्करण आकार आधा स्ट्रिंग है। यह O (n ^ 2) में किया जाता है। परंतु। केवल प्रधान मोडुली की जाँच की जानी चाहिए ताकि हे (n ^ 2 / log (n))
  2. क्रमबद्ध सबसे बड़े मापांक में पहले मापांक / अवशेषों की सूची को क्रमबद्ध करें, यह O (n * log (n)) समय में किया जा सकता है।
  3. लगातार तीन मोडुली / अवशेष देखें जो समान हैं।
  4. किसी तरह लोगों की स्थिति को पुनः प्राप्त!

मुझे लगता है कि उत्तर का सबसे बड़ा सुराग, यह है कि सबसे तेज़ सॉर्ट एल्गोरिदम, ओ (एन * लॉग (एन)) हैं।

गलत

एक सहयोगी द्वारा बताया गया चरण 1 गलत है। यदि हमारे पास 1 की स्थिति 2,12 और 102 है। तो 10 के मापांक लेने पर, वे सभी समान रहते हैं, और फिर भी समान रूप से अलग नहीं होते हैं! माफ़ करना।


यह एक दिलचस्प दृष्टिकोण है, हमें बताएं कि क्या आप पूर्ण समाधान के साथ आते हैं।
जेम्स मैकमोहन

एक नंबर k O (n) बार और उसके बाद O (n) चेक प्रति शिफ्ट एक O (n ^ 2) एल्गोरिथ्म देता है, भले ही आप एक नंबर से शिफ्ट हो रहे हों। आपके एल्गोरिथ्म को एक से अधिक नंबरों से शिफ्ट करना होगा।
ldog

0

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

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

  1. ट्रिम अग्रणी और अनुगामी शून्य।
  2. 1 की तलाश में स्ट्रिंग को स्कैन करें।
  3. जब 1 पाया जाता है:
    1. मान लें कि यह समाधान का मध्य 1 है।
    2. प्रत्येक पहले 1 के लिए, अंतिम 1 की प्रत्याशित स्थिति की गणना करने के लिए इसकी सहेजी गई स्थिति का उपयोग करें।
    3. यदि गणना की स्थिति स्ट्रिंग के अंत के बाद है तो यह समाधान का हिस्सा नहीं हो सकता है, इसलिए उम्मीदवारों की सूची से स्थिति को छोड़ दें।
    4. समाधान की जाँच करें।
  4. यदि समाधान नहीं मिला, तो वर्तमान 1 को उम्मीदवारों की सूची में जोड़ें।
  5. तब तक दोहराएं जब तक कि 1 और न मिल जाए।

अब निम्नलिखित की तरह इनपुट स्ट्रिंग्स के तार पर विचार करें, जिसमें समाधान नहीं होगा:

101
101001
1010010001
101001000100001
101001000100001000001

सामान्य तौर पर, यह प्रपत्र j 0 के k स्ट्रिंग का संयोजन है और इसके बाद शून्य से k-1 तक j के लिए 1 है।

k=2  101
k=3  101001
k=4  1010010001
k=5  101001000100001
k=6  101001000100001000001

ध्यान दें कि सबस्ट्रिंग की लंबाई 1, 2, 3, आदि है। इसलिए, प्रॉब्लम साइज n की लंबाई 1 से k ऐसी है कि n = k (k + 1) / 2 है।

k=2  n= 3  101
k=3  n= 6  101001
k=4  n=10  1010010001
k=5  n=15  101001000100001
k=6  n=21  101001000100001000001

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

k=2  n= 3  p= 1  101
k=3  n= 6  p= 3  101001
k=4  n=10  p= 6  1010010001
k=5  n=15  p=10  101001000100001
k=6  n=21  p=15  101001000100001000001

N और p के बीच का संबंध वह n = p + k है।

स्ट्रिंग से गुजरने की प्रक्रिया में O (n) समय लगता है। हर बार 1 का सामना किया जाता है, अधिकतम (k-1) तुलना की जाती है। चूंकि n = k (k + 1) / 2, n> k ** 2, इसलिए sqrt (n)> k। यह हमें O (n sqrt (n)) या O (n ** 3/2) देता है। ध्यान दें कि यह वास्तव में तंग नहीं हो सकता है, क्योंकि तुलना की संख्या 1 से अधिकतम k तक जाती है, यह पूरे समय k नहीं है। लेकिन मुझे यकीन नहीं है कि गणित में इसका हिसाब कैसे लगाया जाए।

यह अभी भी O (n log (n)) नहीं है। इसके अलावा, मैं साबित नहीं कर सकता कि वे इनपुट सबसे खराब मामले हैं, हालांकि मुझे संदेह है कि वे हैं। मुझे लगता है कि 1 का एक सघन पैकिंग सामने के परिणाम को अंत में एक समान स्पैसर पैकिंग में देता है।

चूंकि किसी को अभी भी यह उपयोगी लग सकता है, यहाँ पर्ल में उस समाधान के लिए मेरा कोड है:

#!/usr/bin/perl

# read input as first argument
my $s = $ARGV[0];

# validate the input
$s =~ /^[01]+$/ or die "invalid input string\n";

# strip leading and trailing 0's
$s =~ s/^0+//;
$s =~ s/0+$//;

# prime the position list with the first '1' at position 0
my @p = (0);

# start at position 1, which is the second character
my $i = 1;

print "the string is $s\n\n";

while ($i < length($s)) {
   if (substr($s, $i, 1) eq '1') {
      print "found '1' at position $i\n";
      my @t = ();
      # assuming this is the middle '1', go through the positions
      # of all the prior '1's and check whether there's another '1'
      # in the correct position after this '1' to make a solution
      while (scalar @p) {
         # $p is the position of the prior '1'
         my $p = shift @p;
         # $j is the corresponding position for the following '1'
         my $j = 2 * $i - $p;
         # if $j is off the end of the string then we don't need to
         # check $p anymore
         next if ($j >= length($s));
         print "checking positions $p, $i, $j\n";
         if (substr($s, $j, 1) eq '1') {
            print "\nsolution found at positions $p, $i, $j\n";
            exit 0;
         }
         # if $j isn't off the end of the string, keep $p for next time
         push @t, $p;
      }
      @p = @t;
      # add this '1' to the list of '1' positions
      push @p, $i;
   }
   $i++;
}

print "\nno solution found\n";

आपका "गैर-समाधान" अनुक्रम गलत है; प्रत्येक 1 का सूचकांक त्रिकोणीय संख्या 1, 3, 6, 10, 15 ... आदि का अनुक्रम है और इसमें संख्या 6, 36 और 66 शामिल हैं, जो एक अंकगणितीय प्रगति बनाते हैं।
जेसन एस

0

1s स्कैन करते समय, उनके पदों को एक सूची में जोड़ें। दूसरी और क्रमिक 1s जोड़ते समय, सूची में उनकी प्रत्येक स्थिति से तुलना करें। रिक्ति currentOne (केंद्र) के बराबर होती है - पिछलाऑन (बाएं)। राइट-साइड बिट currentOne + रिक्ति है। यदि यह 1 है, अंत।

उनके बीच की जगह के साथ लोगों की सूची इसके विपरीत बढ़ती है। बस कहा गया है, यदि आपको 1s (सबसे खराब स्थिति में) के बीच बहुत सारे 0 मिल गए हैं, तो ज्ञात 1s की आपकी सूची धीरे-धीरे बढ़ेगी।

using System;
using System.Collections.Generic;

namespace spacedOnes
{
    class Program
    {
        static int[] _bits = new int[8] {128, 64, 32, 16, 8, 4, 2, 1};

        static void Main(string[] args)
        {
            var bytes = new byte[4];
            var r = new Random();
            r.NextBytes(bytes);
            foreach (var b in bytes) {
                Console.Write(getByteString(b));
            }
            Console.WriteLine();
            var bitCount = bytes.Length * 8;
            var done = false;
            var onePositions = new List<int>();
            for (var i = 0; i < bitCount; i++)
            {
                if (isOne(bytes, i)) {
                    if (onePositions.Count > 0) {
                        foreach (var knownOne in onePositions) {
                            var spacing = i - knownOne;
                            var k = i + spacing;
                            if (k < bitCount && isOne(bytes, k)) {
                                Console.WriteLine("^".PadLeft(knownOne + 1) + "^".PadLeft(spacing) + "^".PadLeft(spacing));
                                done = true;
                                break;
                            }
                        }
                    }
                    if (done) {
                        break;
                    }
                    onePositions.Add(i);
                }
            }
            Console.ReadKey();
        }

        static String getByteString(byte b) {
            var s = new char[8];
            for (var i=0; i<s.Length; i++) {
                s[i] = ((b & _bits[i]) > 0 ? '1' : '0');
            }
            return new String(s);
        }

        static bool isOne(byte[] bytes, int i)
        {
            var byteIndex = i / 8;
            var bitIndex = i % 8;
            return (bytes[byteIndex] & _bits[bitIndex]) > 0;
        }
    }
}

0

मैंने सोचा कि समस्या के 22 वें भोले समाधान को पोस्ट करने से पहले मैं एक टिप्पणी जोड़ूंगा। भोले समाधान के लिए, हमें यह दिखाने की आवश्यकता नहीं है कि स्ट्रिंग में 1 की संख्या सबसे अधिक O (लॉग (n)) पर है, बल्कि यह है कि यह O (sqrt (n * log) (n) पर सबसे अधिक है।

सॉल्वर:

def solve(Str):
    indexes=[]
    #O(n) setup
    for i in range(len(Str)):
        if Str[i]=='1':
            indexes.append(i)

    #O((number of 1's)^2) processing
    for i in range(len(indexes)):
        for j in range(i+1, len(indexes)):
                            indexDiff = indexes[j] - indexes[i]
            k=indexes[j] + indexDiff
            if k<len(Str) and Str[k]=='1':
                return True
    return False

यह मूल रूप से फ्लाईबीवायर के विचार और कार्यान्वयन के समान एक निष्पक्ष बिट है, हालांकि पीछे के बजाय आगे देखना।

लालची स्ट्रिंग बिल्डर:

#assumes final char hasn't been added, and would be a 1 
def lastCharMakesSolvable(Str):
    endIndex=len(Str)
    j=endIndex-1
    while j-(endIndex-j) >= 0:
        k=j-(endIndex-j)
        if k >= 0 and Str[k]=='1' and Str[j]=='1':
            return True
        j=j-1
    return False



def expandString(StartString=''):
    if lastCharMakesSolvable(StartString):
        return StartString + '0'
    return StartString + '1'

n=1
BaseStr=""
lastCount=0
while n<1000000:
    BaseStr=expandString(BaseStr)
    count=BaseStr.count('1')
    if count != lastCount:
        print(len(BaseStr), count)
    lastCount=count
    n=n+1

(मेरे बचाव में, मैं अभी भी 'समझ के अजगर' सीख रहा हूं)

इसके अलावा, स्ट्रिंग्स के लालची भवन से संभावित रूप से उपयोगी आउटपुट, 1 की संख्या में 2 की शक्ति को मारने के बाद एक निरंतर सुसंगत कूद है ... जो कि मैं 2096 की गवाह मारने के लिए इंतजार करने के लिए तैयार नहीं था।

strlength   # of 1's
    1    1
    2    2
    4    3
    5    4
   10    5
   14    8
   28    9
   41    16
   82    17
  122    32
  244    33
  365    64
  730    65
 1094    128
 2188    129
 3281    256
 6562    257
 9842    512
19684    513
29525    1024

0

मैं गणितीय दृष्टिकोण प्रस्तुत करने का प्रयास करूँगा। यह अंत से अधिक की शुरुआत है, इसलिए किसी भी मदद, टिप्पणी, या यहां तक ​​कि विरोधाभास - गहराई से सराहना की जाएगी। हालांकि, अगर यह दृष्टिकोण सिद्ध होता है - एल्गोरिथ्म स्ट्रिंग में एक सीधे-आगे की खोज है।

  1. रिक्त स्थान की एक निश्चित संख्या को देखते हुए kऔर एक स्ट्रिंग S, एक कश्मीर से स्थान दिया गया-त्रिक के लिए खोज लेता है O(n)- हम तो बस हर के लिए परीक्षण 0<=i<=(n-2k)करता है, तो S[i]==S[i+k]==S[i+2k]। परीक्षा होती है O(1)और हम इसे n-kकई बार करते हैं जहां kएक स्थिर होता है, इसलिए यह लेता है O(n-k)=O(n)

  2. हमें लगता है कि वहाँ की संख्या 1और अधिकतम स्थानों के बीच एक व्युत्क्रम अनुपात है जिसे हमें खोजना होगा। यही है, अगर वहाँ कई हैं 1, वहाँ एक ट्रिपल होना चाहिए और यह काफी घना होना चाहिए; यदि केवल कुछ ही हैं 1, तो ट्रिपल (यदि कोई हो) काफी विरल हो सकता है। दूसरे शब्दों में, मैं यह साबित कर सकता हूं कि यदि मेरे पास पर्याप्त है 1, तो इस तरह के ट्रिपल का अस्तित्व होना चाहिए - और 1मेरे पास जितना अधिक होगा, एक अधिक घनी ट्रिपल मिलनी चाहिए। यह कबूतर सिद्धांत द्वारा समझाया जा सकता है - इस पर बाद में विस्तार से उम्मीद है।

  3. कहो कि kमुझे जिन स्थानों को देखना है, उनकी संभावित संख्या पर एक ऊपरी सीमा है । अब, के लिए प्रत्येक 1स्थित में S[i]हम के लिए जांच करने की आवश्यकता 1में S[i-1]और S[i+1], S[i-2]और S[i+2]... S[i-k]और S[i+k]। यह गॉस की सीरीज़ समरी फॉर्मूला के कारण O((k^2-k)/2)=O(k^2)प्रत्येक 1में है । ध्यान दें कि यह खंड 1 से अलग है - मैं रिक्त स्थान की संख्या के लिए ऊपरी सीमा के रूप में हूं , न कि एक स्थिर स्थान के रूप में।Sk

हमें साबित करने की जरूरत है O(n*log(n))। यानी हमें यह दिखाने की जरूरत है कि k*(number of 1's)यह आनुपातिक है log(n)

यदि हम ऐसा कर सकते हैं, तो एल्गोरिथ्म तुच्छ है - प्रत्येक 1के लिए Sजिसका सूचकांक है i, बस 1प्रत्येक पक्ष से दूरी तक देखें k। यदि दो समान दूरी पर पाए गए, तो वापस लौटें iऔर k। फिर, मुश्किल हिस्सा लग रहा होगाk सही साबित और साबित होगा।

मैं वास्तव में यहां आपकी टिप्पणियों की सराहना करूंगा - मैं अपने व्हाइटबोर्ड पर अब तक की सफलता के बिना संबंध kऔर संख्या के बीच संबंध खोजने की कोशिश कर रहा 1हूं।


0

कल्पना:

बस गलत है, लॉग (एन) के बारे में ऊपरी सीमा की संख्या के बारे में बात कर रहे हैं

संपादित करें:

अब मैंने पाया कि कैंटर संख्या (यदि सही है) का उपयोग करते हुए, सेट पर घनत्व (2/3) ^ Log_3 (n) (क्या अजीब कार्य है) और मैं सहमत हूं, लॉग (n) / n घनत्व मजबूत है।

यदि यह ऊपरी सीमा है, तो कम से कम O (n * (3/2) ^ (लॉग (n) / लॉग (3)) में समय की जटिलता और O ((3/2) ^ ( log (n) / log (3)) space जटिलता। (अल्गोरिटम के लिए जस्टिस के जवाब की जाँच करें)

यह अभी भी O से बेहतर है (n ^ 2)

यह फ़ंक्शन ((3/2) ^ (लॉग (n) / लॉग (3)) वास्तव में पहली नजर में n * लॉग (n) जैसा दिखता है।

मुझे यह सूत्र कैसे मिला?

केंटर्स की संख्या को स्ट्रिंग पर लागू करना।
यह मान लें कि स्ट्रिंग की लंबाई 3 ^ p == n
है केंटर स्ट्रिंग की पीढ़ी में प्रत्येक चरण पर आप 2/3 को प्रचलित संख्या में रखते हैं। इस p समय को लागू करें।

इसका मतलब है (n * ((2/3) ^ p) -> ((((3 ^ p)) * (((2/3) ^ p)) शेष और सरलीकरण 2 ^ p के बाद। इसका मतलब 2 ^ p वाले इन 3 ^ p स्ट्रिंग -> (3/2) ^ p वाले। स्थानापन्न p = लॉग (n) / लॉग (3) और मिलता है
((3/2) ^ (लॉग (n) / लॉग (3)))


गलत: कैंटर सेट में घनत्व n ^ log_3 (2) है।
sdcvvc

0

ओ (एन ^ 2) स्थान के साथ एक सरल ओ (एन) समाधान के बारे में कैसे? (इस धारणा का उपयोग करता है कि सभी बिटवाइज़ ऑपरेटर O (1) में काम करते हैं।)

एल्गोरिथ्म मूल रूप से चार चरणों में काम करता है:

स्टेज 1: अपनी मूल संख्या में प्रत्येक बिट के लिए, पता करें कि कितनी दूर हैं, लेकिन केवल एक दिशा पर विचार करें। (मैंने सभी बिट्स को कम से कम महत्वपूर्ण बिट की दिशा में माना।)

स्टेज 2: इनपुट में बिट्स के क्रम को उल्टा करें;

चरण 3: उलटे इनपुट पर चरण 1 को फिर से चलाएँ।

स्टेज 4: स्टेज 1 और स्टेज 3 से परिणामों की तुलना करें। यदि कोई बिट्स समान रूप से ऊपर और नीचे हैं तो हमें हिट होना चाहिए।

ध्यान रखें कि उपरोक्त एल्गोरिथ्म में कोई भी कदम O (n) से अधिक नहीं है। ^ _ ^

एक अतिरिक्त लाभ के रूप में, यह एल्गोरिदम सभी को समान रूप से हर जगह से मिलेगा। इसलिए उदाहरण के लिए यदि आपको "0x0005" का परिणाम मिलता है, तो BOTH 1 और 3 इकाइयों में समान रूप से स्थान दिए गए हैं

मैंने वास्तव में नीचे दिए गए कोड का अनुकूलन करने की कोशिश नहीं की, लेकिन यह काम करने के लिए लगता है कि सी # कोड है।

using System;

namespace ThreeNumbers
{
    class Program
    {
        const int uint32Length = 32;

        static void Main(string[] args)
        {
            Console.Write("Please enter your integer: ");
            uint input = UInt32.Parse(Console.ReadLine());

            uint[] distancesLower = Distances(input);
            uint[] distancesHigher = Distances(Reverse(input));

            PrintHits(input, distancesLower, distancesHigher);
        }

        /// <summary>
        /// Returns an array showing how far the ones away from each bit in the input.  Only 
        /// considers ones at lower signifcant bits.  Index 0 represents the least significant bit 
        /// in the input.  Index 1 represents the second least significant bit in the input and so 
        /// on.  If a one is 3 away from the bit in question, then the third least significant bit 
        /// of the value will be sit.
        /// 
        /// As programed this algorithm needs: O(n) time, and O(n*log(n)) space.  
        /// (Where n is the number of bits in the input.)
        /// </summary>
        public static uint[] Distances(uint input)
        {
            uint[] distanceToOnes = new uint[uint32Length];
            uint result = 0;

            //Sets how far each bit is from other ones. Going in the direction of LSB to MSB
            for (uint bitIndex = 1, arrayIndex = 0; bitIndex != 0; bitIndex <<= 1, ++arrayIndex)
            {
                distanceToOnes[arrayIndex] = result;
                result <<= 1;

                if ((input & bitIndex) != 0)
                {
                    result |= 1;
                }
            }

            return distanceToOnes;
        }

        /// <summary>
        /// Reverses the bits in the input.
        /// 
        /// As programmed this algorithm needs O(n) time and O(n) space.  
        /// (Where n is the number of bits in the input.)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static uint Reverse(uint input)
        {
            uint reversedInput = 0;
            for (uint bitIndex = 1; bitIndex != 0; bitIndex <<= 1)
            {
                reversedInput <<= 1;
                reversedInput |= (uint)((input & bitIndex) != 0 ? 1 : 0);
            }

            return reversedInput;
        }

        /// <summary>
        /// Goes through each bit in the input, to check if there are any bits equally far away in 
        /// the distancesLower and distancesHigher
        /// </summary>
        public static void PrintHits(uint input, uint[] distancesLower, uint[] distancesHigher)
        {
            const int offset = uint32Length - 1;

            for (uint bitIndex = 1, arrayIndex = 0; bitIndex != 0; bitIndex <<= 1, ++arrayIndex)
            {
                //hits checks if any bits are equally spaced away from our current value
                bool isBitSet = (input & bitIndex) != 0;
                uint hits = distancesLower[arrayIndex] & distancesHigher[offset - arrayIndex];

                if (isBitSet && (hits != 0))
                {
                    Console.WriteLine(String.Format("The {0}-th LSB has hits 0x{1:x4} away", arrayIndex + 1, hits));
                }
            }
        }
    }
}

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


0

नीचे एक समाधान है। यहां और वहां कुछ छोटी गलतियां हो सकती हैं, लेकिन विचार ध्वनि है।

संपादित करें: यह n * लॉग (n) नहीं है

PSEUDO कोड:

foreach character in the string
  if the character equals 1 {         
     if length cache > 0 { //we can skip the first one
        foreach location in the cache { //last in first out kind of order
           if ((currentlocation + (currentlocation - location)) < length string)
              if (string[(currentlocation + (currentlocation - location))] equals 1)
                 return found evenly spaced string
           else
              break;
        }
     }
     remember the location of this character in a some sort of cache.
  }

return didn't find evenly spaced string

C # कोड:

public static Boolean FindThreeEvenlySpacedOnes(String str) {
    List<int> cache = new List<int>();

    for (var x = 0; x < str.Length; x++) {
        if (str[x] == '1') {
            if (cache.Count > 0) {
                for (var i = cache.Count - 1; i > 0; i--) {
                    if ((x + (x - cache[i])) >= str.Length)
                        break;

                    if (str[(x + (x - cache[i]))] == '1')
                        return true;                            
                }
            }
            cache.Add(x);                    
        }
    }

    return false;
}

यह काम किस प्रकार करता है:

iteration 1:
x
|
101101001
// the location of this 1 is stored in the cache

iteration 2:
 x
 | 
101101001

iteration 3:
a x b 
| | | 
101101001
//we retrieve location a out of the cache and then based on a 
//we calculate b and check if te string contains a 1 on location b

//and of course we store x in the cache because it's a 1

iteration 4:
  axb  
  |||  
101101001

a  x  b  
|  |  |  
101101001


iteration 5:
    x  
    |  
101101001

iteration 6:
   a x b 
   | | | 
101101001

  a  x  b 
  |  |  | 
101101001
//return found evenly spaced string

1
आपका एल्गोरिथ्म काम करता है, लेकिन आपको यह साबित करने की आवश्यकता है कि यह ओ (एन ^ 2) से कम है। तुच्छ विश्लेषण आपको O (n ^ 2) पर ले जाता है। प्रत्येक 1 के लिए, आप सभी 1s के ऊपर जाते हैं जो इसके पहले थे। जटिलता समारोह बनाना 1 + 2 + 3 + ... + (k / 2-1) = O (k ^ 2) [जहां k 1s की संख्या है]।
अन्ना

मैंने जाँच की और वास्तव में कोई हल नहीं होने के साथ सबसे खराब स्थिति यह है कि O (n * log (n))
Niek H.

0

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

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

-

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

अब हम या तो बजट के भीतर लौट आए हैं, या हम जानते हैं कि बच्चों में से एक के भीतर पूरी तरह से कोई वैध ट्रिपल शामिल नहीं है। इसलिए हमें इंटर-नोड ट्रिपल की जांच करनी चाहिए।

अब चीजें अविश्वसनीय रूप से गड़बड़ हो गई हैं। हम अनिवार्य रूप से सीमा को सीमित करते हुए बच्चों के संभावित सेट पर पुनरावृत्ति करना चाहते हैं। जैसे ही सीमा पर्याप्त रूप से विवश होती है कि भोली एल्गोरिथ्म बजट के तहत चलेगा, आप इसे करते हैं। इसे लागू करने का आनंद लें, क्योंकि मैं गारंटी देता हूं कि यह थकाऊ होगा। एक दर्जन मामलों की तरह है।

-

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

एल्गोरिथ्म का रन समय बिल्कुल भी स्पष्ट नहीं है। यह अनुक्रम के गैर-तुच्छ गुणों पर निर्भर करता है। यदि 1 वास्तव में विरल हैं, तो भोली एल्गोरिथ्म बजट के तहत काम करेगा। यदि 1 घने हैं, तो एक मैच तुरंत मिल जाना चाहिए। लेकिन अगर घनत्व 'सिर्फ सही' है (जैसे ~ n ^ 0.63 के पास, जिसे आप आधार 3 में अंक '2' अंक वाले सभी बिट्स पर सेट करके प्राप्त कर सकते हैं), मुझे नहीं पता कि यह काम करेगा या नहीं। आपको यह साबित करना होगा कि विभाजन प्रभाव काफी मजबूत है।


0

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

वैसे भी यहाँ नीचे कार्यक्रम है। यह एक मोंटे-कार्लो शैली का कार्यक्रम है जो निरंतर n के लिए बड़ी संख्या में परीक्षण NTRIALS चलाता है, और यादृच्छिक रूप से k- मानों की एक सीमा के लिए बिट्ससेट का उपयोग करता है, जो कि सीमा के बीच सीमित घनत्व के साथ बर्नौली प्रक्रियाओं का उपयोग करता है जो निर्दिष्ट किया जा सकता है और चल रहे समय को रिकॉर्ड करता है। समान रूप से दूरी वाले लोगों के एक समूह को खोजने में नाकाम रहने या असफल होने पर, CPU समय में चरणों में नहीं मापा गया। मैंने इसे n = 64, 256, 1024, 4096, 16384 * (अभी भी चल रहा है) के लिए चलाया, पहला परीक्षण 500000 परीक्षणों के साथ चला जो यह देखने के लिए कि कौन-मान सबसे लंबे समय तक चलते हैं, फिर संकीर्णता वाले 5000000 परीक्षणों के साथ एक और परीक्षण- घनत्व यह देखने के लिए फ़ोकस करता है कि वे मान क्या दिखते हैं। सबसे लंबे समय तक चलने वाला समय बहुत कम घनत्व के साथ होता है (जैसे n = 4096 के लिए चलने का समय चोटियों के = 16-64 रेंज में होता है, 4212 कदम @ k = 31 पर औसत रनटाइम के लिए एक कोमल चोटी के साथ, अधिकतम रनटाइम 5101 कदम @ k = 58) पर पहुंच गया। ऐसा लगता है कि यह सबसे खराब स्थिति O (k ^ 2) के लिए N के अत्यंत बड़े मान लेगा, O (n) चरण से बड़ा बनने के लिए जहां आप 1 की स्थिति सूचकांकों को खोजने के लिए बिटस्ट्रिंग को स्कैन करते हैं।

package com.example.math;

import java.io.PrintStream;
import java.util.BitSet;
import java.util.Random;

public class EvenlySpacedOnesTest {
    static public class StatisticalSummary
    {
        private int n=0;
        private double min=Double.POSITIVE_INFINITY;
        private double max=Double.NEGATIVE_INFINITY;
        private double mean=0;
        private double S=0;

        public StatisticalSummary() {}
        public void add(double x) {
            min = Math.min(min, x);
            max = Math.max(max, x);
            ++n;
            double newMean = mean + (x-mean)/n;
            S += (x-newMean)*(x-mean);
            // this algorithm for mean,std dev based on Knuth TAOCP vol 2
            mean = newMean;
        }
        public double getMax() { return (n>0)?max:Double.NaN; }
        public double getMin() { return (n>0)?min:Double.NaN; }
        public int getCount() { return n; }
        public double getMean() { return (n>0)?mean:Double.NaN; }
        public double getStdDev() { return (n>0)?Math.sqrt(S/n):Double.NaN; } 
        // some may quibble and use n-1 for sample std dev vs population std dev    
        public static void printOut(PrintStream ps, StatisticalSummary[] statistics) {
            for (int i = 0; i < statistics.length; ++i)
            {
                StatisticalSummary summary = statistics[i];
                ps.printf("%d\t%d\t%.0f\t%.0f\t%.5f\t%.5f\n",
                        i,
                        summary.getCount(),
                        summary.getMin(),
                        summary.getMax(),
                        summary.getMean(),
                        summary.getStdDev());
            }
        }
    }

    public interface RandomBernoulliProcess // see http://en.wikipedia.org/wiki/Bernoulli_process
    {
        public void setProbability(double d);
        public boolean getNextBoolean();
    }

    static public class Bernoulli implements RandomBernoulliProcess
    {
        final private Random r = new Random();
        private double p = 0.5;
        public boolean getNextBoolean() { return r.nextDouble() < p; }
        public void setProbability(double d) { p = d; }
    }   
    static public class TestResult {
        final public int k;
        final public int nsteps;
        public TestResult(int k, int nsteps) { this.k=k; this.nsteps=nsteps; } 
    }

    ////////////
    final private int n;
    final private int ntrials;
    final private double pmin;
    final private double pmax;
    final private Random random = new Random();
    final private Bernoulli bernoulli = new Bernoulli();
    final private BitSet bits;
    public EvenlySpacedOnesTest(int n, int ntrials, double pmin, double pmax) {
        this.n=n; this.ntrials=ntrials; this.pmin=pmin; this.pmax=pmax;
        this.bits = new BitSet(n);
    }

    /*
     * generate random bit string
     */
    private int generateBits()
    {
        int k = 0; // # of 1's
        for (int i = 0; i < n; ++i)
        {
            boolean b = bernoulli.getNextBoolean();
            this.bits.set(i, b);
            if (b) ++k;
        }
        return k;
    }

    private int findEvenlySpacedOnes(int k, int[] pos) 
    {
        int[] bitPosition = new int[k];
        for (int i = 0, j = 0; i < n; ++i)
        {
            if (this.bits.get(i))
            {
                bitPosition[j++] = i;
            }
        }
        int nsteps = n; // first, it takes N operations to find the bit positions.
        boolean found = false;
        if (k >= 3) // don't bother doing anything if there are less than 3 ones. :(
        {       
            int lastBitSetPosition = bitPosition[k-1];
            for (int j1 = 0; !found && j1 < k; ++j1)
            {
                pos[0] = bitPosition[j1];
                for (int j2 = j1+1; !found && j2 < k; ++j2)
                {
                    pos[1] = bitPosition[j2];

                    ++nsteps;
                    pos[2] = 2*pos[1]-pos[0];
                    // calculate 3rd bit index that might be set;
                    // the other two indices point to bits that are set
                    if (pos[2] > lastBitSetPosition)
                        break;
                    // loop inner loop until we go out of bounds

                    found = this.bits.get(pos[2]);
                    // we're done if we find a third 1!
                }
            }
        }
        if (!found)
            pos[0]=-1;
        return nsteps;
    }

    /*
     * run an algorithm that finds evenly spaced ones and returns # of steps.
     */
    public TestResult run()
    {
        bernoulli.setProbability(pmin + (pmax-pmin)*random.nextDouble());
        // probability of bernoulli process is randomly distributed between pmin and pmax

        // generate bit string.
        int k = generateBits();
        int[] pos = new int[3];
        int nsteps = findEvenlySpacedOnes(k, pos);
        return new TestResult(k, nsteps); 
    }

    public static void main(String[] args)
    {
        int n;
        int ntrials;
        double pmin = 0, pmax = 1;
        try {
            n = Integer.parseInt(args[0]);
            ntrials = Integer.parseInt(args[1]);
            if (args.length >= 3)
                pmin = Double.parseDouble(args[2]);
            if (args.length >= 4)
                pmax = Double.parseDouble(args[3]);
        }
        catch (Exception e)
        {
            System.out.println("usage: EvenlySpacedOnesTest N NTRIALS [pmin [pmax]]");
            System.exit(0);
            return; // make the compiler happy
        }

        final StatisticalSummary[] statistics;
        statistics=new StatisticalSummary[n+1];
        for (int i = 0; i <= n; ++i)
        {
            statistics[i] = new StatisticalSummary();
        }

        EvenlySpacedOnesTest test = new EvenlySpacedOnesTest(n, ntrials, pmin, pmax);
        int printInterval=100000;
        int nextPrint = printInterval;
        for (int i = 0; i < ntrials; ++i)
        {
            TestResult result = test.run();
            statistics[result.k].add(result.nsteps);
            if (i == nextPrint)
            {
                System.err.println(i);
                nextPrint += printInterval;
            }
        }
        StatisticalSummary.printOut(System.out, statistics);
    }
}

0
# <algorithm>
def contains_evenly_spaced?(input)
  return false if input.size < 3
  one_indices = []
  input.each_with_index do |digit, index|
    next if digit == 0
    one_indices << index
  end
  return false if one_indices.size < 3
  previous_indexes = []
  one_indices.each do |index|
    if !previous_indexes.empty?
      previous_indexes.each do |previous_index|
        multiple = index - previous_index
        success_index = index + multiple
        return true if input[success_index] == 1
      end
    end
    previous_indexes << index
  end
  return false
end
# </algorithm>

def parse_input(input)
  input.chars.map { |c| c.to_i }
end

मुझे लाखों अंकों के साथ सबसे खराब स्थिति में परेशानी हो रही है। /dev/urandomअनिवार्य रूप से फ़ज़िंग आपको O (n) देता है, लेकिन मुझे पता है कि सबसे खराब स्थिति इससे भी बदतर है। मैं अभी नहीं बता सकता कि कितना बुरा है। छोटे के लिए n, यह चारों ओर इनपुट खोजने के लिए तुच्छ है 3*n*log(n), लेकिन इस विशेष समस्या के लिए विकास के कुछ अन्य क्रम से उन लोगों को अलग करना आश्चर्यजनक रूप से कठिन है।

क्या कोई भी व्यक्ति जो सबसे खराब स्थिति में काम कर रहा था, एक हजार से अधिक लंबाई वाली स्ट्रिंग उत्पन्न कर सकता है?


जैसा कि मैंने अपने उत्तर में बताया है, किसी भी संख्या के अंकों के खराब (हालांकि सबसे खराब स्थिति में नहीं) तारों को उत्पन्न करना आसान है: 1 s को उन पदों p पर रखें, जिनमें उनके टर्नरी प्रतिनिधित्व में कोई "1" नहीं है (अर्थात पदों 2, 6, 8, 18, 20, 24, 26, 54, 56, 60 ...: research.att.com/ सूत्र / परिणाम / परिणाम देखें)। 3 ^ 13 million 1 मिलियन के लिए, इसमें 2 ^ 13 13 8000 1s है। इस तरह के तार पर चलने का समय time n ^ (1.26) होगा - जो अभी भी ऐसे छोटे n के लिए O (n log n) से अलग करना मुश्किल हो सकता है। यह कोशिश करो और देखो।
श्रीवत्सआर

-2

राबिन-कार्प एल्गोरिथ्म का एक अनुकूलन आपके लिए संभव हो सकता है। इसकी जटिलता 0 (n) है, इसलिए यह आपकी मदद कर सकती है।

देखिए http://en.wikipedia.org/wiki/Rabin-Karp_string_search_algorithm


3
राबिन-कार्प सटीक सब्सट्रिंग खोजने के लिए स्ट्रिंग हैशिंग का उपयोग करते हैं, इसलिए यह समस्या के साथ मदद नहीं कर सकता है।
रॉबर्ट पार्कर

-3

यह एक समाधान हो सकता है? I ', यह निश्चित नहीं है कि यह O (nlogn) है, लेकिन मेरी राय में यह O (n²) से बेहतर है क्योंकि ट्रिपल खोजने का एकमात्र तरीका प्राइम नंबर वितरण होगा।

इसमें सुधार की गुंजाइश है, दूसरा पाया गया 1 अगला पहला हो सकता है। कोई त्रुटि जाँच भी नहीं।

#include <iostream>

#include <string>

int findIt(std::string toCheck) {
    for (int i=0; i<toCheck.length(); i++) {
        if (toCheck[i]=='1') {
            std::cout << i << ": " << toCheck[i];
            for (int j = i+1; j<toCheck.length(); j++) {
                if (toCheck[j]=='1' && toCheck[(i+2*(j-i))] == '1') {
                    std::cout << ", " << j << ":" << toCheck[j] << ", " << (i+2*(j-i)) << ":" << toCheck[(i+2*(j-i))] << "    found" << std::endl;
                    return 0;
                }
            }
        }
    }
    return -1;
}

int main (int agrc, char* args[]) {
    std::string toCheck("1001011");
    findIt(toCheck);
    std::cin.get();
    return 0;
}

1
तकनीकी रूप से यह O (n ^ 2) है। हर बार चलने पर एन के आधे हिस्से पर औसतन लूप इटररेट होगा। इसलिए इसे O (n * (n / 2)) के रूप में लिखा जा सकता है, और जिसे O (n ^ 2) के लिए सरल बनाया जा सकता है
रॉबर्ट पार्कर

हम्म, ऐसा लगता है कि आप सही हैं। यह एक साधारण समस्या नहीं है, बस सभी 1 O (n) को खोजने के लिए, O (logn) जटिलता के साथ किसी भी आगे की खोज / तुलना के लिए ज्यादा जगह नहीं है।
DaClown

-3

मुझे लगता है कि इस एल्गोरिथ्म में O (n log n) जटिलता (C ++, DevStudio 2k5) है। अब, मुझे इसकी जटिलता का निर्धारण करने के लिए एक एल्गोरिथ्म का विश्लेषण करने के तरीके का विवरण नहीं पता है, इसलिए मैंने कुछ मीट्रिक एकत्रित जानकारी को कोड में जोड़ा है। कोड किसी भी दिए गए इनपुट के लिए 1 और 0 के अनुक्रम पर किए गए परीक्षणों की संख्या को गिनता है (उम्मीद है, मैंने एल्गोरिथ्म की एक गेंद नहीं बनाई है)। हम O मान के विरुद्ध परीक्षण की वास्तविक संख्या की तुलना कर सकते हैं और देखें कि क्या कोई सहसंबंध है या नहीं।

#include <iostream>
using namespace std;

bool HasEvenBits (string &sequence, int &num_compares)
{
  bool
    has_even_bits = false;

  num_compares = 0;

  for (unsigned i = 1 ; i <= (sequence.length () - 1) / 2 ; ++i)
  {
    for (unsigned j = 0 ; j < sequence.length () - 2 * i ; ++j)
    {
      ++num_compares;
      if (sequence [j] == '1' && sequence [j + i] == '1' && sequence [j + i * 2] == '1')
      {
        has_even_bits = true;
        // we could 'break' here, but I want to know the worst case scenario so keep going to the end
      }
    }
  }

  return has_even_bits;
}

int main ()
{
  int
    count;

  string
    input = "111";

  for (int i = 3 ; i < 32 ; ++i)
  {
    HasEvenBits (input, count);
    cout << i << ", " << count << endl;
    input += "0";
  }
}

यह प्रोग्राम प्रत्येक स्ट्रिंग लंबाई के लिए परीक्षणों की संख्या को 32 अक्षरों तक बढ़ाता है। यहाँ परिणाम है:

 n  Tests  n log (n)
=====================
 3     1     1.43
 4     2     2.41
 5     4     3.49
 6     6     4.67
 7     9     5.92
 8    12     7.22
 9    16     8.59
10    20    10.00
11    25    11.46
12    30    12.95
13    36    14.48
14    42    16.05
15    49    17.64
16    56    19.27
17    64    20.92
18    72    22.59
19    81    24.30
20    90    26.02
21   100    27.77
22   110    29.53
23   121    31.32
24   132    33.13
25   144    34.95
26   156    36.79
27   169    38.65
28   182    40.52
29   196    42.41
30   210    44.31
31   225    46.23

मैंने 'एन लॉग एन' मान भी जोड़ा है। दो परिणामों के बीच सहसंबंध देखने के लिए अपनी पसंद के रेखांकन उपकरण का उपयोग करके इन्हें प्लॉट करें। क्या यह विश्लेषण n के सभी मूल्यों का विस्तार करता है? मुझे नहीं पता।


यह एक सही सहसंबंध नहीं है, मैं सहमत हूं। हालाँकि, वक्र n n n 2 की तुलना में n लॉग एन के करीब है।
स्किज

3
एक लाख या अधिक के माध्यम से इनपुट आकार को पंप करने का प्रयास करें। छोटे इनपुट पर वक्र अक्सर एल्गोरिदम के वक्रों के समान दिखता है जो स्पष्ट रूप से बेहतर होते हैं जब इनपुट आकार को पंप किया जाता है।
निक लार्सन

बाहरी एक से बंधे हुए आंतरिक एक के साथ पाश के लिए एक डबल एक त्रिकोणीय आकार के लिए बनाता है, जो अभी भी जटिलता में ओ (एन ^ 2) है। सभी के बारे में सोचो (i, j) जैसे कि मैं [0, n] और j में [0, n-2 * i], आपके पास एक त्रिकोण है, और एक त्रिकोण के क्षेत्र में एक द्विघात प्रवृत्ति है।
मथिउ एम।

सटीक होना, टेस्ट = (एन ^ 2-2 एन) / 4 के लिए भी एन; जाहिर है द्विघात।
दादाजी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.