ट्रिकी Google साक्षात्कार प्रश्न


169

मेरा एक दोस्त नौकरी के लिए साक्षात्कार कर रहा है। साक्षात्कार के सवालों में से एक मुझे सोच रहा था, बस कुछ प्रतिक्रिया चाहता था।

2 गैर-नकारात्मक पूर्णांक हैं: i और j। निम्नलिखित समीकरण को देखते हुए, i और j को इस तरह से व्यवस्थित करने के लिए एक (इष्टतम) समाधान ढूंढें कि आउटपुट को हल किया जाए।

2^i * 5^j

तो पहले कुछ दौर इस तरह दिखेंगे:

2^0 * 5^0 = 1
2^1 * 5^0 = 2
2^2 * 5^0 = 4
2^0 * 5^1 = 5
2^3 * 5^0 = 8
2^1 * 5^1 = 10
2^4 * 5^0 = 16
2^2 * 5^1 = 20
2^0 * 5^2 = 25

जैसा कि हो सकता है, मैं एक पैटर्न नहीं देख सकता। तुम्हारे विचार?


63
प्रोग्रामर समय के संदर्भ में इष्टतम एल्गोरिथ्म दो नेस्टेड छोरों के साथ उत्पन्न करने के लिए है, फिर सॉर्ट करें। वे इस तरह से सवाल क्यों पूछते हैं?
टॉम ज़िक

21
आप कौन से अंक अधिक हैं, यह देखकर संक्रमण बिंदु निर्धारित करने में सक्षम हो सकते हैं। 2^2 < 5लेकिन 2^3 > 5इसलिए उस बिंदु पर आप जम्मू में वृद्धि करते हैं। मुझे लगता है कि आप O (nlgn) के बजाय O (n) में आउटपुट का उत्पादन कर सकते हैं। @ टॉम-ज़िनच दो नेस्टेड लूप्स हे (एन ^ 2)। यह प्रश्न बहुत मान्य है
मिखाइल

1
केवल एक आउटपुट है, इसलिए इष्टतम समाधान O (n) है। नीचे मेरा समाधान पढ़ें
मिखाइल

3
इसी तरह के एक प्रश्न को स्पष्ट रूप से पहले संबोधित किया गया है: stackoverflow.com/questions/4600048/nth-ugly-number

1
... और ओपी को शायद पहले से ही एक जवाब चुनना चाहिए। आखिरकार, वह पहले से ही बहुत अच्छे हैं।
1'11

जवाबों:


123

दीजकस्ट्रा "प्रोग्रामिंग के एक अनुशासन" में एक शानदार समाधान प्राप्त करता है। वह समस्या को हैमिंग तक पहुंचाता है। यहाँ दिज्क्स्ट्रा के समाधान का मेरा कार्यान्वयन है।

int main()
{
    const int n = 20;       // Generate the first n numbers

    std::vector<int> v(n);
    v[0] = 1;

    int i2 = 0;             // Index for 2
    int i5 = 0;             // Index for 5

    int x2 = 2 * v[i2];     // Next two candidates
    int x5 = 5 * v[i5];

    for (int i = 1; i != n; ++i)
    {
        int m = std::min(x2, x5);
        std::cout << m << " ";
        v[i] = m;

        if (x2 == m)
        {
            ++i2;
            x2 = 2 * v[i2];
        }
        if (x5 == m)
        {
            ++i5;
            x5 = 5 * v[i5];
        }
    }

    std::cout << std::endl;
    return 0;
}

18
प्रासंगिक लिंक: en.wikipedia.org/wiki/Regular_number#Al एल्गोरिदम । मुझे नहीं लगता कि यह एक बहुत अच्छा साक्षात्कार प्रश्न है। यहाँ दिज्क्स्त्र द्वारा एक हस्तलिखित पेपर) दिया गया है जहाँ वह इस समस्या के लिए एक एल्गोरिथ्म प्रदान करता है और सिद्ध करता है: cs.utexas.edu/users/EWD/ewd07xx/EWD792.PDF
Elian Ebbing

जब लक्ष्य "i और j पर पुनरावृति करने के लिए" आपको कम भंडारण क्षमता की आवश्यकता होती है, तो एक FIFO पर्याप्त है। मेरा पायथन समाधान देखें।
GaBorgulya

7
जब लक्ष्य "आई और जे पर पुनरावृति करना" है, तो यह एक ही समस्या नहीं है।
mhum

यह वास्तव में अच्छा कार्यान्वयन है, न्यूनतम स्मृति का उपयोग करके। भले ही आप केवल एक नंबर चाहते हैं, लेकिन यह रैखिक मेमोरी है।
थॉमस अहले

1
@ThomasAhle है, तो आप को देखा है पता नहीं यह लेकिन यह अंत है कि अलगाव में एन-वें संख्या की गणना करने में सक्षम है पर कोड है। जैसे एक अरबवाँ नंबर
विल नेस

47

यहाँ यह करने का एक और अधिक परिष्कृत तरीका है (मेरे पिछले उत्तर की तुलना में अधिक परिष्कृत, यह है):

कल्पना करें कि संख्याएं एक मैट्रिक्स में रखी गई हैं:

     0    1    2    3    4    5   -- this is i
----------------------------------------------
0|   1    2    4    8   16   32
1|   5   10   20   40   80  160
2|  25   50  100  200  400  800
3| 125  250  500 1000 2000 ...
4| 625 1250 2500 5000 ...
j on the vertical

आपको इस मैट्रिक्स को 'चलना' चाहिए, जो शुरू में है (0,0)। आपको यह भी ध्यान रखने की आवश्यकता है कि आपकी संभावित अगली चालें क्या हैं। जब आप शुरू करते (0,0)हैं तो आपके पास केवल दो विकल्प होते हैं: या तो (0,1)या (1,0): चूंकि मूल्य (0,1)छोटा है, आप इसे चुनते हैं। फिर अपनी अगली पसंद के लिए भी ऐसा ही करें (0,2)या (1,0)। अब तक, आपके पास निम्न सूची है 1, 2, 4:। आपका अगला कदम (1,0)तब से है जब मूल्य वहाँ से छोटा है (0,3)। हालांकि, आप अब तीन अपनी अगली चाल के लिए विकल्प हैं: या तो (0,3), या (1,1), या (2,0)

सूची प्राप्त करने के लिए आपको मैट्रिक्स की आवश्यकता नहीं है, लेकिन आपको अपने सभी विकल्पों पर नज़र रखने की आवश्यकता है (यानी जब आप 125+ पर पहुंचेंगे, तो आपके पास 4 विकल्प होंगे)।


मैंने इसे वोट दिया क्योंकि मैं उसी तर्ज पर सोच रहा था, लेकिन सामान्य स्थिति में, क्या यह ओ (i ^ 2 * 2) जैसा कुछ नहीं होगा? आपको प्रत्येक संख्या के लिए कई संख्याओं की जांच करनी होगी जो आप आउटपुट करते हैं।
टॉम ज़िक

1
@ क्या आपको एक से अधिक नंबर की जांच करनी है, लेकिन यह उतना बुरा नहीं है: जब आप 125 और 625 के बीच संख्याओं को आउटपुट करते हैं, तो आपको 4 मानों को देखना होगा। 625 और 3025 के बीच, आप 5 मूल्यों को देखते हैं। तो वास्तव में, यह jहर 1 आउटपुट के लिए जाँच करता है
vlad

+1: इस प्रश्न के साथ संयोजित करें: stackoverflow.com/questions/5000836/search-algorithm और ऐसा लगता है कि हमारे पास O (n) समाधान है।

@ मॉरन डार, मैं उस एल्गोरिथ्म के लिए $ 25 का भुगतान नहीं करना चाहता, लेकिन यह दिलचस्प दिखता है।
vlad

1
वास्तव में, j ~ n^0.5एन-वें मान के लिए एक क्रम में, क्योंकि nमान i x jविमान पर एक क्षेत्र को भरते हैं। तो यह अहंकार O(n^1.5)समय है, O(n^0.5)अंतरिक्ष के साथ । लेकिन उसी स्थान के साथ एक रैखिक समय अहंकार मौजूद होता है n^0.5, और नीचे दिए गए उत्तर से मिनी-हीप अहंकार उसी स्थान पर O(n*log(n))समय होता है n^0.5
विल नेस

25

मिन-हीप का प्रयोग करें।

1 डाल दिया।

निकालने-मिन। कहते हैं तुम एक्स हो जाओ।

2x और 5x को ढेर में दबाएं।

दोहराएँ।

X = 2 ^ i * 5 ^ j को संग्रहीत करने के बजाय, आप कस्टम (i, j) स्टोर कर सकते हैं और कस्टम तुलना फ़ंक्शन का उपयोग कर सकते हैं।


1
ढेर अपने संचालन पर lg n समय देगा, जो जटिलता को n lg n पर धकेलता है।
corsiKa

@glow: हां, मुझे अब तक कोई भी O (n) समाधान पोस्ट नहीं हुआ है, हालाँकि :-)

@ लेबल: यह टिप्पणी पुरानी है। ऐसा लगता है कि उन्हें (1,1) से (4,0) तक भी समस्याएँ होंगी। लेकिन इसे युवा मैट्रिक्स के रूप में देखना (vlad का जवाब देखें) वास्तव में O (n) समय एल्गोरिथ्म की अनुमति देता है।

@ मॉरन: मुझे नहीं लगता कि उस समाधान में कुछ भी गलत है। निश्चित रूप से पहले 30 तत्वों में कुछ भी गलत नहीं है, जिसे मैंने अभी चेक किया है (जो कि (1,1) -> (4,0) केस को कवर करेगा)।
abeln

@ पर: हाँ, वास्तव में इसे चलाने की कोशिश नहीं की थी :-) शायद इसकी शुद्धता का एक आसान प्रमाण भी है। FWIW, यह पहले से ही मेरे +1 है।

13

एक FIFO- आधारित समाधान को कम भंडारण क्षमता की आवश्यकता होती है। पायथन कोड।

F = [[1, 0, 0]]             # FIFO [value, i, j]
i2 = -1; n2 = n5 = None     # indices, nexts
for i in range(1000):       # print the first 1000
    last = F[-1][:]
    print "%3d. %21d = 2^%d * 5^%d" % tuple([i] + last)
    if n2 <= last: i2 += 1; n2 = F[i2][:]; n2[0] *= 2; n2[1] += 1
    if n5 <= last: i2 -= 1; n5 = F.pop(0); n5[0] *= 5; n5[2] += 1
    F.append(min(n2, n5))

उत्पादन:

  0.                     1 = 2^0 * 5^0
  1.                     2 = 2^1 * 5^0
  2.                     4 = 2^2 * 5^0
 ...
998. 100000000000000000000 = 2^20 * 5^20
999. 102400000000000000000 = 2^27 * 5^17

6

यह O(n)कार्यात्मक भाषाओं में करना बहुत आसान है । सूची lकी 2^i*5^jसंख्या बस के रूप में परिभाषित किया जा सकता है 1और उसके बाद 2*lऔर 5*lविलय कर दिया। यहाँ यह हास्केल में कैसा दिखता है:

merge :: [Integer] -> [Integer] -> [Integer]
merge (a:as) (b:bs)   
  | a < b   = a : (merge as (b:bs))
  | a == b  = a : (merge as bs)
  | b > a   = b : (merge (a:as) bs)

xs :: [Integer]
xs = 1 : merge (map(2*)xs) (map(5*)xs)

mergeसमारोह आप निरंतर समय में एक नया मान देता है। इसलिए करता है mapऔर इसलिए ऐसा करता है l


मुझे लगता है कि 'k' परिभाषित नहीं है
Ither

2
चलो unionइसके बजाय इस "मर्ज" फ़ंक्शन को कॉल करते हैं , क्योंकि यह डुप्लिकेट को हटा रहा है। mergeके एक भाग के रूप में mergesort, दोनों इनपुट अनुक्रमों से आने वाले डुप्लिकेट को संरक्षित करना चाहिए। Data.List.Orderedसंबंधित सामान के लिए पैकेज देखें ।
विल नेस

1
के लिए +1 Data.List.Ordered.union। यह एक पंक्ति बनाता है:xs = 1 : union (map (2*) xs) (map (5*) xs)
23

@GaBorgulya हाँ, यह सूची में पाँच बार [1, 2, 4, 5,...]शामिल है इसलिए इसमें शामिल है 5*4
थॉमस अहले

1
@Phob हाँ, यह Data.List.Ordered.unionफ़ंक्शन है। से भ्रमित नहीं होना है Data.List.union
थॉमस अहले

5

आपको उनमें से अलग-अलग घातांक का ट्रैक रखना होगा, और उनकी रकम क्या होगी

इसलिए f(0,0) --> 1 अब आप उनमें से एक को बढ़ाना शुरू करते हैं:

f(1,0) = 2
f(0,1) = 5

इसलिए हम जानते हैं कि 2 अगला है - हम यह भी जानते हैं कि हम राशि का घातांक 5 तक बढ़ा सकते हैं।

आप इस तरह आगे-पीछे होते रहें, जब तक कि आप अपने राउंड की संख्या को समाप्त नहीं कर लेते।


हाँ यही है। आप प्रत्येक राउंड के लिए एक O (1) ऑपरेशन करते हैं। कभी-कभी आप राउंड को जल्दी करते हैं, लेकिन जब आप उस राउंड में पहुंचते हैं तो आपको वहां ऐसा करने की जरूरत नहीं होती है, इसलिए यह खुद ही काम करता है।
corsiKa

19
आप (1,1) से (4,0) कैसे जाते हैं? कृपया ठीक से बताएं कि आपका एल्गोरिथ्म क्या है।

समस्या यह है कि, आपके पास केवल दो वृद्धिशील संभावनाएं नहीं हैं - उदाहरण के लिए, आप f(*,2)सिर्फ इसलिए नहीं कर रहे हैं क्योंकि आपने पाया है f(a1,b+1)>f(a2,b)। वृद्धिशील दृष्टिकोण अंतत: आपके द्वारा पहले से आउटपुट किए गए क्षेत्र को पड़ोसी से जोड़े जाने की संख्या को बढ़ाएगा।
comingstorm

@ user515430 ने एक ऐसा कार्यान्वयन प्रदान किया जो मेरे लंच ब्रेक पर मैं जितना कर सकता था, उससे कहीं अधिक था, लेकिन यही मैं पाने की कोशिश कर रहा था।
corsiKa

4

डायनेमिक प्रोग्रामिंग का उपयोग करके आप इसे O (n) में कर सकते हैं। जमीनी सच्चाई यह है कि i और j का कोई भी मान हमें 0 नहीं दे सकता है, और 1 पाने के लिए दोनों मानों को 0 होना चाहिए;

TwoCount[1] = 0
FiveCount[1] = 0

// function returns two values i, and j
FindIJ(x) {
    if (TwoCount[x / 2]) {
        i = TwoCount[x / 2] + 1
        j = FiveCount[x / 2]
    }
    else if (FiveCount[x / 5]) {
        i = TwoCount[x / 2]
        j = FiveCount[x / 5] + 1
    }
}

जब भी आप इस फ़ंक्शन को कॉल करते हैं, अगर मैं और जम्मू सेट हैं, यदि वे अशक्त नहीं हैं, तो आबाद करें TwoCountऔरFiveCount


सी ++ जवाब। खराब कोडिंग शैली के लिए खेद है, लेकिन मैं जल्दी में हूँ :(

#include <cstdlib>
#include <iostream>
#include <vector>

int * TwoCount;
int * FiveCount;

using namespace std;

void FindIJ(int x, int &i, int &j) {
        if (x % 2 == 0 && TwoCount[x / 2] > -1) {
                cout << "There's a solution for " << (x/2) << endl;
                i = TwoCount[x / 2] + 1;
                j = FiveCount[x / 2];
        } else if (x % 5 == 0 && TwoCount[x / 5] > -1) {
                cout << "There's a solution for " << (x/5) << endl;
                i = TwoCount[x / 5];
                j = FiveCount[x / 5] + 1;
        }    
}

int main() {
        TwoCount = new int[200];
        FiveCount = new int[200];

        for (int i = 0; i < 200; ++i) {
                TwoCount[i] = -1;
                FiveCount[i] = -1;
        }

        TwoCount[1] = 0;
        FiveCount[1] = 0;

        for (int output = 2; output < 100; output++) {
                int i = -1;
                int j = -1;
                FindIJ(output, i, j);
                if (i > -1 && j > -1) {
                        cout << "2^" << i << " * " << "5^" 
                                     << j << " = " << output << endl;
                        TwoCount[output] = i;
                        FiveCount[output] = j;
                }
        }    
}

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


4
यह एक दिलचस्प जवाब की तरह दिखता है, लेकिन मैं यह देखने में विफल रहता हूं कि यह वास्तव में कैसे काम करता है। क्या आप अधिक विवरण जोड़ सकते हैं?
डेविड ब्रूनेल

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

आप सभी कहे जाने वालों के लिए C ++ संस्करण पोस्ट किया। @ आपकी टिप्पणियाँ सही हैं, लेकिन मेरा मूल कोड छद्म कोड था और मैं स्क्रिप्टिंग शब्दों में सोच रहा था, इसलिए पूर्णांक विभाजन नहीं और शून्य प्रविष्टि और मान 0 के प्रवेश के बीच भेद करना
मिखाइल

यह कोड सभी प्राकृतिक संख्याओं की गणना करता है, इसलिए, नीचे दिए गए "अलबामा में लॉस्ट" द्वारा उत्तर के लिए @ThomasAhle की टिप्पणी के अनुसार, अनुक्रम की संख्या O(exp(sqrt(n)))उत्पन्न करने के लिए , यह लेता है nरैखिक एल्गोरिथ्म मौजूद है, जैसे थॉमसले द्वारा दिया गया।
विल नेस

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

2

इसे दूसरी दिशा से देखने की कोशिश क्यों नहीं की गई। मूल सूत्र के विरुद्ध संभावित उत्तरों का परीक्षण करने के लिए एक काउंटर का उपयोग करें। छद्म कोड के लिए क्षमा करें।

for x = 1 to n
{
  i=j=0
  y=x
  while ( y > 1 )
  {
    z=y
    if y divisible by 2 then increment i and divide y by 2
    if y divisible by 5 then increment j and divide y by 5

    if y=1 then print i,j & x  // done calculating for this x

    if z=y then exit while loop  // didn't divide anything this loop and this x is no good 
  }
}

यह लगभग चलता है O(4^sqrt(n))क्योंकि nthअनुक्रम की संख्या लगभग उस आकार की है।
थॉमस अहले

2

यह OEIS में प्रासंगिक प्रविष्टि है।

ऐसा लगता है कि पहले कुछ शब्द उत्पन्न करके आदेशित अनुक्रम प्राप्त करना संभव है

1 2 4 5

और फिर, दूसरे कार्यकाल से शुरू होकर अगले दो को प्राप्त करने के लिए 4 और 5 से गुणा करें

1 2 4 5 8 10

1 2 4 5 8 10 16 20

1 2 4 5 8 10 16 20 25

और इसी तरह...

सहज रूप से, यह सही लगता है, लेकिन निश्चित रूप से एक सबूत गायब है।


2
गलत :( [4 5 8 से 10 1 2 16 20 से 25 32 40 50 64 80 100 125 128 160 200 250 256 320 400 500 625 ] हालांकि 500 <512 = 2 ^ 9 <625
GaBorgulya

1
@NateKerkhofs, 512 उत्पन्न होता है, लेकिन यह क्रम से बाहर है क्योंकि 512 पहले से उत्पन्न 625 से कम है; आउटपुट को क्रम में रखने के लिए एल्गोरिथ्म को और अधिक तर्क की आवश्यकता होगी - इस प्रकार एल्गोरिथ्म प्रस्तावित के समान सरल नहीं है और समान एल्गोरिथ्म बिल्कुल नहीं है।
गॉर्डनबूड

1

आप जानते हैं कि log_2 (5) = 2.32। इससे हम ध्यान दें कि 2 ^ 2 <5 और 2 ^ 3> 5।

अब संभावित उत्तरों का एक मैट्रिक्स देखें:

j/i  0   1   2   3   4   5
 0   1   2   4   8  16  32
 1   5  10  20  40  80 160 
 2  25  50 100 200 400 800
 3 125 250 500 ...

अब, इस उदाहरण के लिए, क्रम में संख्याओं का चयन करें। आदेश देना होगा:

j/i  0   1   2   3   4   5
 0   1   2   3   5   7  10
 1   4   6   8  11  14  18
 2   9  12  15  19  23  27
 3  16  20  24...

ध्यान दें कि हर पंक्ति शुरू होने वाली पंक्ति के पीछे 2 कॉलम शुरू करती है। उदाहरण के लिए, i = 0 j = 1 सीधे i = 2 j = 0 के बाद आता है।

एक एल्गोरिथ्म हम इस पैटर्न से प्राप्त कर सकते हैं इसलिए (मान जा> i):

int i = 2;
int j = 5;
int k;
int m;

int space = (int)(log((float)j)/log((float)i));
for(k = 0; k < space*10; k++)
{
    for(m = 0; m < 10; m++)
    {
        int newi = k-space*m;
        if(newi < 0)
            break;
        else if(newi > 10)
            continue;
        int result = pow((float)i,newi) * pow((float)j,m);
        printf("%d^%d * %d^%d = %d\n", i, newi, j, m, result);
    }
}   

नोट: यहाँ कोड i और j के घातांक का मान 10 से कम है। आप इस एल्गोरिथ्म को आसानी से किसी अन्य मनमाने सीमा में फिट कर सकते हैं।

नोट: इस एल्गोरिथ्म के लिए चलने का समय पहले n उत्तर के लिए O (n) है।

नोट: इस एल्गोरिथ्म के लिए अंतरिक्ष जटिलता O (1) है


आपने लिखा है "हर पंक्ति शुरू होने वाली पंक्ति के पीछे 2 कॉलम शुरू करती है"। हालाँकि 2 ^ 9 = 512 और 5 ^ 4 = 625, इसलिए यह पंक्ति 4 के लिए सही नहीं है
गाबोरगुला

@ user678105 आप सही हैं। यह कोड काम नहीं करता है। क्षमा करें सब। लॉग के राउंड ऑफ और मेरी धारणा के कारण यह कोड काम नहीं करता है कि यह कोई फर्क नहीं पड़ा।
KLee1

1
यहां बताया गया है कि आप इसे कैसे ठीक करते हैं। अभिन्न गुणांक वाले बिंदुओं से भरे हुए x (x, y) समतल पर (0,1) से (log2 (5), 0) तक एक रेखा खींचें। (0,0) शीर्ष बाएं कोने में है। X अक्ष दाईं ओर जाता है, Y अक्ष नीचे जाता है। अब (0,0) मूल बिंदु से एक रेखा खींचें जो पहली पंक्ति के लंबवत है। अब दूसरी पंक्ति के साथ पहली पंक्ति को स्लाइड करें, आगे और आगे उत्पत्ति से दूर, और पूर्णांक-निर्देशांक बिंदुओं को इकट्ठा करें क्योंकि वे पार हो गए हैं। {2,3,5} -गैरनेटेड सीक्वेंस के लिए, यह (i, j, k) स्पेस में घूमता हुआ प्लेन होगा। यदि आप इस विचार को कोड में अनुवाद कर सकते हैं, तो मुझे एक चिल्लाहट दें। :)
विल नेस

1

मेरा कार्यान्वयन निम्नलिखित विचारों पर आधारित है:

  • दो कतारों का उपयोग करें क्यू 2 और क्यू 5, दोनों को 1 के साथ शुरू किया गया। हम दोनों कतार को क्रमबद्ध क्रम में रखेंगे।
  • हर चरण में, छोटी संख्या के तत्व MIN को Q2 या Q5 से हटाएं और प्रिंट करें। यदि दोनों क्यू 2 और क्यू 5 में एक ही तत्व है - दोनों को हटा दें। इस नंबर को प्रिंट करें। यह मूल रूप से दो क्रमबद्ध सरणियों का विलय है - प्रत्येक चरण में सबसे छोटा तत्व और अग्रिम चुनें।
  • Enqueue MIN * 2 से Q2 और MIN * 5 से Q5। यह परिवर्तन Q2 / Q5 के क्रमबद्ध को नहीं तोड़ा जा रहा है, क्योंकि MIN पिछले MIN संख्या से अधिक है।

उदाहरण:

Start with 1 and 1 (to handle i=0;j=0 case):
  Q2: 1
  Q5: 1
Dequeue 1, print it and enqueue 1*2 and 1*5:
  Q2: 2
  Q5: 5
Pick 2 and add 2*2 and 2*5:
  Q2: 4
  Q5: 5 10
Pick 4 and add 4*2 and 4*5:
  Q2: 8
  Q5: 5 10 20
....

जावा में कोड:

public void printNumbers(int n) {
    Queue<Integer> q2 = new LinkedList<Integer>();
    Queue<Integer> q5 = new LinkedList<Integer>();
    q2.add(1);
    q5.add(1);
    for (int i = 0; i < n; i++) {
        int a = q2.peek();
        int b = q5.peek();
        int min = Math.min(a, b);
        System.out.println(min);
        if (min == a) {
            q2.remove();
        }
        if (min == b) {
            q5.remove();
        }
        q2.add(min * 2);
        q5.add(min * 5);
    }
}

0

परिणामों की गणना और उनके लिए मूल्यों के साथ मिलकर एक क्रमबद्ध सूची में डाल दिया, iऔरj


वह संभवतः आपके अनुक्रम के बाद के अंत में आपको छेद देगा। जैसे कि आपके पास होगा, 2^n*5^nलेकिन 2^(n+1)*5^(n-1)जो छोटा नहीं है।
थॉमस अहले

@ थोमस मुझे यकीन नहीं है कि मैं यहाँ आपके तर्क का पालन करूँगा। यदि आप एक की गणना करते हैं, तो आप दूसरे की गणना क्यों नहीं करेंगे?
vlad

2
@vlad आपको अपने i's' पर एक सीमा रखने की जरूरत है j, है ना? अन्यथा आप कभी भी सॉर्ट करने की स्थिति में नहीं आएंगे, और इसलिए आप कभी भी एक मान नहीं लौटाएंगे। लेकिन nआपके द्वारा चुनी गई किसी भी सीमा के लिए , आपकी सूची त्रुटिपूर्ण होगी।
थॉमस अहले

@ अपने तर्क अभी भी समझ में नहीं आता है। ओपी ने कभी अपने परिणामों की सूची को समाप्त नहीं किया। यदि वह करता है, तो आप अधिकतम iऔर पा सकते हैं j
vlad

1
@vlad जैसा कि मैंने आपका उत्तर पढ़ा, आप पहले "परिणाम" / 2^i*5^jमानों की गणना करते हैं, और फिर उन्हें सॉर्ट करते हैं। यदि आपके पास "परिणाम" की सीमित संख्या नहीं है, तो आप कभी छंटनी के कदम पर कैसे पहुंचेंगे?
थॉमस अहले

0

Edsger Dijkstra (http://www.cs.utexas.edu/users/EWD/ewd07xx/EWD792.PDF) द्वारा यूज़र 515430 द्वारा लागू किया गया एल्गोरिथ्म शायद उतना ही तेज़ है जितना आप प्राप्त कर सकते हैं। मैं हर नंबर को कॉल करता हूं 2^i * 5^jजो "विशेष नंबर" का एक रूप है । अब vlads उत्तर होगाO(i*j) लेकिन एक दोहरे एल्गोरिथ्म के साथ, एक विशेष संख्याओं को उत्पन्न करने के लिए O(i*j)और एक उन्हें सॉर्ट करने के लिए (जुड़े हुए लेख के अनुसार भी)O(i*j)

लेकिन दीजकस्ट्रा के एल्गोरिदम की जांच करें (नीचे देखें)। इस मामले nमें हम जितने विशेष नंबर पैदा कर रहे हैं, उतने ही हैं i*j। हम एक बार लूप कर रहे हैं, 1 -> nऔर प्रत्येक लूप में हम एक निरंतर क्रिया करते हैं। तो यह एल्गोरिथम भी हैO(i*j) । और एक बहुत तेज धधकते निरंतर के साथ भी।

GMP (C ++ आवरण) और निर्भरता के साथ C ++ में मेरा कार्यान्वयन boost::lexical_cast, हालांकि इसे आसानी से हटाया जा सकता है (मैं आलसी हूं, और जो बूस्ट का उपयोग नहीं करता है?)। के साथ संकलित किया g++ -O3 test.cpp -lgmpxx -o test। Q6600 पर Ubuntu 10.10 time ./test 1000000देता है 1145ms

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <gmpxx.h>

int main(int argc, char *argv[]) {
    mpz_class m, x2, x5, *array, r;
    long n, i, i2, i5;

    if (argc < 2) return 1;

    n = boost::lexical_cast<long>(argv[1]);

    array = new mpz_class[n];
    array[0] = 1;

    x2 = 2;
    x5 = 5;
    i2 = i5 = 0;

    for (i = 1; i != n; ++i) {
        m = std::min(x2, x5);

        array[i] = m;

        if (x2 == m) {
            ++i2;
            x2 = 2 * array[i2];
        }

        if (x5 == m) {
            ++i5;
            x5 = 5 * array[i5];
        }
    }

    delete [] array;
    std::cout << m << std::endl;

    return 0;
}

0

यदि आप पंक्ति के रूप में i और पंक्ति के रूप में एक मैट्रिक्स खींचते हैं तो आप पैटर्न देख सकते हैं। I = 0 से शुरू करें और फिर मैट्रिक्स के शीर्ष तक पहुँचने तक 2 पंक्तियों और दाएं 1 कॉलम पर जाकर मैट्रिक्स को पीछे छोड़ें। फिर मैं + 1, आदि ...

तो i = 7 के लिए आप इस तरह से यात्रा करते हैं:

7, 0 -> 5, 1 -> 3, 2 -> 1, 3

और मैं = 8 के लिए:

8, 0 -> 6, 1 -> 4, 2 -> 2, 3 -> 0, 4

यहां यह जावा में i = 9 तक जा रहा है। यह मैट्रिक्स स्थिति (i, j) और मूल्य को प्रिंट करता है।

for(int k = 0; k < 10; k++) {

    int j = 0;

    for(int i = k; i >= 0; i -= 2) {

        int value = (int)(Math.pow(2, i) * Math.pow(5, j));
        System.out.println(i + ", " + j + " -> " + value);
        j++;
    }
}

0

मेरा अंतर्ज्ञान :

यदि मैं 1 के रूप में प्रारंभिक मूल्य लेता हूं जहां मैं = 0, j = 0, तो मैं अगले नंबर बना सकता हूं (2 ^ 1) (5 ^ 0), (2 ^ 2) (5 ^ 0), (2 ^ 0) * (5 ^ 1), ... अर्थात 2,4,5 ।।

किसी भी बिंदु पर कहना है कि मेरा नंबर x है। फिर मैं निम्नलिखित तरीकों से अगले नंबर बना सकता हूं:

  • x * २
  • x * ४
  • x * ५

स्पष्टीकरण :

Since new numbers can only be the product with 2 or 5.
But 4 (pow(2,2)) is smaller than 5, and also we have to generate 
Numbers in sorted order.Therefore we will consider next numbers
be multiplied with 2,4,5.
Why we have taken x*4 ? Reason is to pace up i, such that it should not 
be greater than pace of j(which is 5 to power). It means I will 
multiply my number by 2, then by 4(since 4 < 5), and then by 5 
to get the next three numbers in sorted order.

परीक्षण चालन

We need to take an Array-list of Integers, let say Arr.

Also put our elements in Array List<Integers> Arr.
Initially it contains Arr : [1]
  • X = 1 से शुरू करें।

    अगले तीन नंबर 1 * 2, 1 * 4, 1 * 5 [2,4,5] हैं; आगमन [1,2,4,5]

  • अब x = 2

    अगली तीन संख्याएँ हैं [4,8,10] {चूँकि 4 पहले से ही हैं, हम इसे अनदेखा कर देंगे} [8,10]; आगमन [1,2,4,5,8,10]

  • अब x = 4

    अगले तीन नंबर [8,16,20] {8 पहले से ही इसे नजरअंदाज कर दिया}} [16,20] Arr [1,2,4,5,8,10,16,20]

  • x = 5

    अगली तीन संख्याएँ [१०,२०,२५] {१०,२०} पहले से ही [२५] जोड़ा गया है अर्र [१,२,४,५,16,१०,१६,२०,२५]

समाप्ति की स्थिति

 Terminating condition when Arr last number becomes greater 
 than (5^m1 * 2^m2), where m1,m2 are given by user.

विश्लेषण

 Time Complexity : O(K) : where k is numbers possible between i,j=0 to 
 i=m1,j=m2.
 Space Complexity : O(K)

0

बस उत्सुक था कि अगले हफ्ते क्या उम्मीद की जाए और यह सवाल मिल गया है।

मुझे लगता है, विचार 2 ^ है मैं 5 ^ j के रूप में उस बड़े चरणों में नहीं बढ़ता। तो जब तक अगले j- कदम बड़ा नहीं होगा मैं बढ़ाएँ

C ++ में उदाहरण (Qt वैकल्पिक है):

QFile f("out.txt"); //use output method of your choice here
f.open(QIODevice::WriteOnly);
QTextStream ts(&f);

int i=0;
int res=0;
for( int j=0; j<10; ++j )
{
    int powI = std::pow(2.0,i );
    int powJ = std::pow(5.0,j );
    while ( powI <= powJ  ) 
    {
        res = powI * powJ;
        if ( res<0 ) 
            break; //integer range overflow

        ts<<i<<"\t"<<j<<"\t"<<res<<"\n";
        ++i;
        powI = std::pow(2.0,i );

    }
}

उत्पादन:

i   j   2^i * 5^j
0   0   1
1   1   10
2   1   20
3   2   200
4   2   400
5   3   4000
6   3   8000
7   4   80000
8   4   160000
9   4   320000
10  5   3200000
11  5   6400000
12  6   64000000
13  6   128000000
14  7   1280000000

यह समाधान कुछ संयोजनों को याद करता है। उदाहरण के लिए, यह उस मामले की जाँच नहीं करता जहाँ मैं = 1, j = 2 किसी भी मामले में जहाँ मैं = 1 और j> 1 उस मामले के लिए ..
फेडेरिको

@ फ़ेडरिको: आप सही कह रहे हैं! कोई आश्चर्य नहीं कि मैं 6 साल के अंतराल के साथ दो बार
Google-

0

यहाँ मेरा समाधान है

#include <stdio.h>
#include <math.h>
#define N_VALUE 5
#define M_VALUE  5

int n_val_at_m_level[M_VALUE];

int print_lower_level_val(long double val_of_higher_level, int m_level)
{
int  n;
long double my_val;


for( n = n_val_at_m_level[m_level]; n <= N_VALUE; n++) {
    my_val =  powl(2,n) * powl(5,m_level);
    if(m_level != M_VALUE && my_val > val_of_higher_level) {
        n_val_at_m_level[m_level] = n;
        return 0;
    }
    if( m_level != 0) {
        print_lower_level_val(my_val, m_level - 1);
    }
    if(my_val < val_of_higher_level || m_level == M_VALUE) {
        printf("    %Lf n=%d m = %d\n", my_val, n, m_level);
    } else {
        n_val_at_m_level[m_level] = n;
        return 0;
    }
 }
 n_val_at_m_level[m_level] = n;
 return 0;
 }


 main()
 {
    print_lower_level_val(0, M_VALUE); /* to sort 2^n * 5^m */
 }

परिणाम :

1.000000 n = 0 m = 0
2.000000 n = 1 m = 0
4.000000 n = 2 m = 0
5.000000 n = 0 m = 1
8.000000 n = 3 m = 0
10.000000 n = 1 m = 1
16.000000 n = 4 m = 0
20.000000 n = 2 m = 1
25.000000 n = 0 m = 2
32.000000 n = 5 m = 0
40.000000 n = 3 m = 1
50.000000 n = 1 m = 2
80.000000 n = 4 m = 1
100.000000 n = 2 m = 2
125.000000 n = 0 m = 3
160.000000 n = 5 m = 1
200.000000 n = 3 m = 2
250.000000 n = 1 m = 3
400.000000 n = 4 m = 2
500.000000 n = 2 m = 3
625.000000 n = 0 m = 4
800.000000 n = 5 m = 2
1000.000000 n = 3 m = 3
1250.000000 n = 1 m = 4
2000.000000 n = 4 m = 3
2500.000000 n = 2 m = 4
3125.000000 n = 0 m = 5
4000.000000 n = 5 m = 3
5000.000000 n = 3 m = 4
6250.000000 n = 1 m = 5
10000.000000 n = 4 m = 4
12500.000000 n = 2 m = 5
20000.000000 n = 5 m = 4
25000.000000 n = 3 m = 5
50000.000000 n = 4 m = 5
100000.000000 n = 5 m = 5

0

मुझे पता है कि मैं गलत हूँ, लेकिन यहाँ एक बहुत ही सरल अनुमान है क्योंकि इसमें 2,3,5 जैसी कई संख्याएँ शामिल नहीं हैं। हम जानते हैं कि किसी भी i, j 2 ^ i * 5 ^ j के लिए अगला अनुक्रम 2 ^ (i-2) * 5 ^ (j + 1) होगा। Google q होने के नाते इसका एक सरल उपाय होना चाहिए।

def func(i, j):
 print i, j, (2**i)*(5**j)

imax=i=2
j=0
print "i", "j", "(2**i)*(5**j)"

for k in range(20):
    func(i,j)
    j=j+1; i=i-2
    if(i<0):
        i = imax = imax+1
        j=0

यह उत्पादन के रूप में:

i j (2**i)*(5**j)
2 0 4
0 1 5
3 0 8
1 1 10
4 0 16
2 1 20
0 2 25
5 0 32
3 1 40
1 2 50
6 0 64
4 1 80
2 2 100
0 3 125
7 0 128
5 1 160
3 2 200
1 3 250
8 0 256
6 1 320

यह 20, या 200 तक काम कर सकता है, लेकिन कुछ बिंदु पर यह कुछ संख्याओं को छोड़ना शुरू कर देगा और / या उन्हें गलत क्रम में आउटपुट करेगा।
विल नेस

0

यदि आप वास्तव में क्या हो रहा है, जब हम अभिव्यक्ति में i या j बढ़ाते हैं 2^i * 5^j कर रहे हैं, तो आप या तो एक और 2 या दूसरे से गुणा कर रहे हैं 5. यदि हम समस्या को शांत करते हैं जैसे - i और j का एक विशेष मूल्य दिया जाता है, तो आप आगे कैसे पाएंगे अधिक से अधिक मूल्य, समाधान स्पष्ट हो जाता है।

यहां ऐसे नियम बताए गए हैं, जिनसे हम काफी सहज ज्ञान प्राप्त कर सकते हैं:

  • यदि i > 1अभिव्यक्ति में 2s ( ) की एक जोड़ी है , तो हमें अगली सबसे बड़ी संख्या प्राप्त करने के लिए उन्हें 5 से बदलना चाहिए। इस प्रकार, i -= 2और j += 1
  • अन्यथा, यदि कोई 5 ( j > 0) है, तो हमें इसे तीन 2s से बदलने की आवश्यकता है। तो j -= 1और i += 3
  • अन्यथा, हमें न्यूनतम मूल्य बढ़ाने के लिए सिर्फ एक और 2 की आपूर्ति करने की आवश्यकता है। i += 1

यहाँ रूबी में कार्यक्रम है:

i = j = 0                                                                       
20.times do                                                                     
  puts 2**i * 5**j

  if i > 1                                                                      
    j += 1                                                                      
    i -= 2                                                                      
  elsif j > 0                                                                   
    j -= 1                                                                      
    i += 3                                                                      
  else                                                                          
    i += 1                                                                      
  end                                                                                                                                                               
end

यह 'i' के रूप में काम नहीं करता है, कभी भी 4 से बड़ा नहीं होता है, इसलिए 32 (2 ^ 5) का कोई गुणक कभी नहीं दिखाई देगा।
थ्रीप्लसोनोन

0

अगर हमें जावा कलेक्शन का उपयोग करने की अनुमति है तो हम इन नंबरों को O (n ^ 2) में ले सकते हैं

public static void main(String[] args) throws Exception {
    int powerLimit = 7;  
     int first = 2;
     int second = 5;
    SortedSet<Integer> set = new TreeSet<Integer>();

    for (int i = 0; i < powerLimit; i++) {
        for (int j = 0; j < powerLimit; j++) {
            Integer x = (int) (Math.pow(first, i) * Math.pow(second, j));
            set.add(x);
        }
    }

    set=set.headSet((int)Math.pow(first, powerLimit));

    for (int p : set)
        System.out.println(p);
}

यहाँ पॉवरलिमिट को बहुत सावधानी से इनिशियलाइज़ करना होगा !! निर्भर करता है कि आपको कितने नंबर चाहिए।


यह गलत परिणाम उत्पन्न करता है: 2 ^ 6 * 5 = 320 से पहले 2 ^ 8 = 256 गायब है। गणना क्षेत्र त्रिकोणीय है, आयताकार नहीं।
विल नेस

@WillNess कैसे ?? जब मैं पॉवरलिमिट = 9 सेट कर रहा हूं, तो यह स्निपेट 1 2 4 5 8 10 16 20 25 32 32 50 50 100 100 125 128 160 200 250 256 320 400 500
कवि टेम्परेचर जूल

नहीं, यह 100 नंबर का उत्पादन करता है। आप कैसे जानते हैं कि कहाँ रुकना है? आपको यह समझाना होगा। --- मैंने आपके कोड स्निपेट में मौजूद 7 का उल्लेख किया है। इसके लिए एक मान्य उत्तर होने के लिए, आपको यह बताना होगा कि किसी दी गई संख्या के लिए सीमा कैसे निर्धारित की जाए, और यह कितनी संख्याओं से आगे निकलेगी
विल नेस

0

यहाँ Scala के साथ मेरा प्रयास है:

case class IndexValue(twosIndex: Int, fivesIndex: Int)
case class OutputValues(twos: Int, fives: Int, value: Int) {
  def test(): Boolean = {
    Math.pow(2,  twos) * Math.pow(5, fives) == value
  }
}

def run(last: IndexValue = IndexValue(0, 0), list: List[OutputValues] = List(OutputValues(0, 0, 1))): List[OutputValues] = {
  if (list.size > 20) {
    return list
  }

  val twosValue = list(last.twosIndex).value * 2
  val fivesValue = list(last.fivesIndex).value * 5

  if (twosValue == fivesValue) {
    val lastIndex = IndexValue(last.twosIndex + 1, last.fivesIndex + 1)
    val outputValues = OutputValues(value = twosValue, twos = list(last.twosIndex).twos + 1, fives = list(last.fivesIndex).fives + 1)
    run(lastIndex, list :+ outputValues)
  } else if (twosValue < fivesValue) {
    val lastIndex = IndexValue(last.twosIndex + 1, last.fivesIndex)
    val outputValues = OutputValues(value = twosValue, twos = list(last.twosIndex).twos + 1, fives = list(last.twosIndex).fives)
    run(lastIndex, list :+ outputValues)
  } else {
    val lastIndex = IndexValue(last.twosIndex, last.fivesIndex + 1)
    val outputValues = OutputValues(value = fivesValue, twos = list(last.fivesIndex).twos, fives = list(last.fivesIndex).fives + 1)
    run(lastIndex, list :+ outputValues)
  }
}

val initialIndex = IndexValue(0, 0)
run(initialIndex, List(OutputValues(0, 0, 1))) foreach println

आउटपुट:

OutputValues(0,0,1)
OutputValues(1,0,2)
OutputValues(2,0,4)
OutputValues(0,1,5)
OutputValues(3,0,8)
OutputValues(1,1,10)
OutputValues(4,0,16)
OutputValues(2,1,20)
OutputValues(0,2,25)
OutputValues(5,0,32)
OutputValues(3,1,40)
OutputValues(1,2,50)
OutputValues(6,0,64)
OutputValues(4,1,80)
OutputValues(2,2,100)
OutputValues(0,3,125)
OutputValues(7,0,128)
OutputValues(5,1,160)
OutputValues(3,2,200)
OutputValues(1,3,250)
OutputValues(8,0,256)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.