2011-11-30 11 views
7

मैं एक समारोहहास्केल: रैखिक समय में एक क्रमपरिवर्तन को उलटने के लिए, केवल सूचीबद्ध करता

invert :: [Int] -> [Int] 

कि मानता है कि अपने इनपुट [0..(n-1)] का क्रमपरिवर्तन है, और उसके प्रतिलोम देता है परिभाषित करना चाहते हैं का उपयोग कर। क्या कोई इसे केवल सूचियों और tuples (बिना सरणी के) का उपयोग कर परिभाषित कर सकता है ताकि यह रैखिक समय में चलता है?

यह मुख्य रूप से अकादमिक हित से बाहर है; वास्तविक कोड में मैं Array या STArray या इसी तरह का उपयोग कर सकता हूं।

+0

आप एक क्रमचय के विपरीत है क्या व्याख्या कर सकते हैं सूची? – Tarrasch

+0

तार्रास, यहां एक नज़र डालें: http://mathworld.wolfram.com/InversePermutation.html – Kenji

+1

मुझे यह प्रश्न पसंद है, लेकिन मुझे विश्वास है कि ओ (एन) में ऐसा करना संभव नहीं है। एक सीधी विधि को सॉर्टिंग की आवश्यकता होती है। यदि हास्केल ने ओ (1) अनुक्रमण और संलग्न करने का समर्थन किया है, तो यह संभव होगा। 'डेटा.लिस्ट' में कई ऑपरेशन ओ (एन) हैं, इसलिए हम दक्षता के मामले में बहुत सीमित हैं। – Kenji

उत्तर

2

रैखिक समय, बस एक शुरुआती नोट के बारे में निश्चित नहीं है।

λ> (\x -> map snd $ sort $ zip x [1..(length x)]) [3,8,5,10,9,4,6,1,7,2] 
[8,10,1,6,3,7,9,2,5,4] 
+0

यदि आप 'ओ (एन)' सॉर्टिंग एल्गोरिदम प्रदान कर सकते हैं तो योग्य होगा ... – leftaroundabout

+0

धन्यवाद, लेकिन यह तुलनात्मक प्रकार का उपयोग करता है, इसलिए यह Ω (n लॉग n) होगा। – Prateek

+7

वैसे, आप 'लंबाई x' को छोड़ सकते हैं, बस' [1 ..] 'के साथ ज़िप करें। – leftaroundabout

1

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

+1

मैं भी उस पर विश्वास करने के इच्छुक हूं। लेकिन फिर, 'रिवर्स' का "स्पष्ट" पुनरावर्ती कार्यान्वयन वर्गबद्ध समय है, और यहां एक आसान रैखिक समय कार्यान्वयन भी है। 'Minout :: [int] -> Int' पर विचार करें जो अलग nonnegative पूर्णांक की एक सूची लेता है, और इनपुट में सबसे छोटा nonnegative पूर्णांक * नहीं * प्रस्तुत करता है। यह भी कुछ चतुरता के साथ, रैखिक समय में किया जा सकता है। तो मुझे आश्चर्य है ... – Prateek

+0

@prateek: मुझे यकीन नहीं है कि मुझे आपका अंक मिला है या नहीं। बेशक, 'minout' में एक स्पष्ट रैखिक-समय कार्यान्वयन है; मैं यह भी कहूंगा कि उसे बहुत अधिक चतुरता की आवश्यकता नहीं है: 'minout = foldr (max। Succ) 0'। लेकिन यह 'उलटा' से कैसे संबंधित है?'रिवर्स' और 'इनवर्टर' के बीच का अंतर यह है कि पूर्व क्रम में अपना परिणाम बना सकता है, जबकि बाद वाला-मेरा मानना ​​है-नहीं। –

+0

मेरा (कुछ हद तक कमजोर) बिंदु सिर्फ वही था जो रैखिक समय में सूचियों के साथ करना मुश्किल लग सकता है, इसलिए शायद 'उलटा' करने का एक चालाक तरीका है जिसे मैंने नहीं सोचा है। मुझे नहीं पता कि कोई नकारात्मक परिणाम कैसे साबित कर सकता है। (वैसे, आपके द्वारा दिया गया कार्य 'minout' की गणना नहीं करता है जैसा कि मैंने इसे परिभाषित किया है - यह सूची के अधिकतम तत्व 1 + की गणना करता है: 'minout [0,2,4]' '1' होना चाहिए) – Prateek

2

तो, यह "केवल सूचियों" का उपयोग नहीं करता है। लेकिन यह बहुत अच्छा लग रहा था।

import qualified Data.Vector as V 

invert :: [Int] -> [Int] 
invert list = V.toList $ vec V.// assocs 
    where vec = V.fromList list -- better ideas for initializing vec? 
     assocs = zip (map pred list) [1..] 

जो दावा है कि //हे (एन) है the Vector package देखें। खैर, यह ओ (एन + एम) कहता है, लेकिन इस मामले में, n = m

मैंने इसे ghci में लोड किया और उसी जवाब को डिमिट्री के रूप में मिला। :)

+2

पर इन-इन-लिस्ट-इन-रैखिक-टाइम-का उपयोग-बस वेक्टरों को वास्तव में बड़े tuples के रूप में सोचें। ;) –

+0

[monadic प्रारंभिकरण का उपयोग कर एक वैकल्पिक कार्यान्वयन] (http://stackoverflow.com/a/6737456/98117)। (नोट: यह शून्य-आधारित अनुक्रमण का उपयोग करता है) – hammar

0

क्रमपरिवर्तन, तो शिथिल चक्रों की सूची के रूप में प्रतिनिधित्व कर रहे हैं

invert :: [[Int]] -> [[Int]] 
invert = map reverse 

रैखिक समय में चलाता है। मुझे यकीन नहीं है कि अलग-अलग प्रतिनिधित्वों के बीच आगे और आगे परिवर्तित करने के लिए एक रैखिक तरीका है या नहीं।

1

वहाँ वास्तविक प्रश्न के लिए एक सकारात्मक जवाब नहीं लगता है के रूप में, मैं गैर समाधान की सूची में मेरा धोखा जोड़ देंगे:

invert :: [Int] -> [Int] 
invert lst = take lng $ map (fromIntegral.(`mod`h)) $ iterate (`div`h) 
       $ sum $ zipWith (\k x->k*h^x) [0..] lst 
    where h::Integer 
     h = fromIntegral lng 
     lng = length lst 
+0

मुझे आश्चर्य है कि किस बिंदु पर 'के * एच^एक्स' एक महत्वपूर्ण मंदी कारक बन गया है। –

+0

बहुत जल्द, दुर्भाग्य से! जैसा कि मैंने कहा, यह वास्तव में एक समाधान नहीं है; वास्तव में, एक्सपोनिएशन इसे _O_ (_n_ log _n_) से बहुत धीमा कर देता है, जैसे _O_ (_n_ ² लॉग _n_)। – leftaroundabout

+0

यह कुछ हाइपोटेटिक क्वांटम कंप्यूटर पर देशी मनमानी-परिशुद्धता एक्सपोनेंटिएशन के साथ _O_ (_n_) होगा, हालांकि ... – leftaroundabout

संबंधित मुद्दे