2012-03-20 15 views
5

एक अनुक्रम जिसमें तत्वों का मूल्य पहले घटता है और फिर वृद्धि को वी-अनुक्रम कहा जाता है। वैध वी-अनुक्रम में घटती हुई कम से कम एक तत्व कम होने और कम से कम एक तत्व होना चाहिए।बढ़ते क्रम अनुक्रम

उदाहरण के लिए, "5 3 1 9 17 23" एक मान्य वी-अनुक्रम है जिसमें कम से कम 5 और 3, और बढ़ती भुजा में 9 तत्व 17, 17 और 23 में दो तत्व हैं। लेकिन अनुक्रम "6 4 2" या "8 10 15" अनुक्रम में से कोई भी नहीं है क्योंकि "6 4 2" में बढ़ते हिस्से में कोई तत्व नहीं है जबकि "8 10 15" में घटते हिस्से में कोई तत्व नहीं है।

एन संख्याओं के अनुक्रम को देखते हुए यह सबसे लंबा (अनिवार्य रूप से संगत) उप अनुक्रम नहीं है जो वी-अनुक्रम है?

क्या यह ओ (एन)/ओ (लॉगन)/ओ (एन^2) में ऐसा करना संभव है?

+0

परिणाम को में संख्या के रूप में वे मूल अनुक्रम में कर रहे हैं, ठीक उसी क्रम में हैं, लेकिन सन्निहित होने की ज़रूरत नहीं? – gcbenison

+0

हां बिल्कुल। इसका मतलब है कि आप मूल अनुक्रम से तत्वों को हटा सकते हैं लेकिन जोड़ नहीं सकते हैं और हटाने की संख्या न्यूनतम होनी चाहिए। –

+0

http://stackoverflow.com/questions/9764512/longest-subsequence-that-first-increases-then-decreases/9764580#9764580 –

उत्तर

4

समाधान सबसे लंबे समय तक घटने वाले बाद के समाधान के समान है। अंतर यह है कि अब प्रत्येक तत्व के लिए आपको दो मानों को स्टोर करने की आवश्यकता है - इस तत्व से शुरू होने वाले सबसे लंबे वी अनुक्रम की लंबाई क्या है और इस पर शुरू होने वाले सबसे लंबे समय तक घटने की लंबाई क्या है। कृपया typical non-decreasing subsequence समाधान के समाधान पर नज़र डालें और मुझे विश्वास है कि यह एक अच्छी पर्याप्त टिप होना चाहिए। मेरा मानना ​​है कि आप जो सर्वोत्तम जटिलता प्राप्त कर सकते हैं वह है ओ (एन * लॉग (एन)), लेकिन जटिलता का समाधान ओ (एन^2) हासिल करना आसान है।

उम्मीद है कि इससे मदद मिलती है।

0

यहां पाइथन में इज़ोमोर्फियस के ऊपर बहुत उपयोगी संकेत के आधार पर एक कार्यान्वयन है। यह बढ़ती अनुवर्ती समस्या के this implementation पर बनाता है। यह इज़ोमोर्फियस कहता है, "अब तक का सबसे अच्छा वी पाया गया है" के साथ-साथ "अब तक के सबसे बढ़ते अनुक्रमों" का ट्रैक रखते हुए। ध्यान दें कि एक वी को विस्तारित करने के बाद, एक घटते अनुक्रम को विस्तारित करने से अलग नहीं है। इसके अलावा पहले उम्मीदवारों के बढ़ते बाद से नए उम्मीदवार वी के "स्पॉन" करने का नियम होना चाहिए।

from bisect import bisect_left 

def Vsequence(seq): 
    """Returns the longest (non-contiguous) subsequence of seq that 
    first increases, then decreases (i.e. a "V sequence"). 

    """ 
    # head[j] = index in 'seq' of the final member of the best increasing 
    # subsequence of length 'j + 1' yet found 
    head = [0] 
    # head_v[j] = index in 'seq' of the final member of the best 
    # V-subsequence yet found 
    head_v = [] 
    # predecessor[j] = linked list of indices of best increasing subsequence 
    # ending at seq[j], in reverse order 
    predecessor = [-1] * len(seq) 
    # similarly, for the best V-subsequence 
    predecessor_v = [-1] * len(seq) 
    for i in xrange(1, len(seq)): 

     ## First: extend existing V's via decreasing sequence algorithm. 
     ## Note heads of candidate V's are stored in head_v and that 
     ## seq[head_v[]] is a non-increasing sequence 
     j = -1 ## "length of best new V formed by modification, -1" 
     if len(head_v) > 0: 
      j = bisect_left([-seq[head_v[idx]] for idx in xrange(len(head_v))], -seq[i]) 

      if j == len(head_v): 
       head_v.append(i) 
      if seq[i] > seq[head_v[j]]: 
       head_v[j] = i 

     ## Second: detect "new V's" if the next point is lower than the head of the 
     ## current best increasing sequence. 
     k = -1 ## "length of best new V formed by spawning, -1" 
     if len(head) > 1 and seq[i] < seq[head[-1]]: 
      k = len(head) 

      extend_with(head_v, i, k + 1) 

      for idx in range(k,-1,-1): 
       if seq[head_v[idx]] > seq[i]: break 
       head_v[idx] = i 

     ## trace new predecessor path, if found 
     if k > j: 
      ## It's better to build from an increasing sequence 
      predecessor_v[i] = head[-1] 
      trace_idx = predecessor_v[i] 
      while trace_idx > -1: 
       predecessor_v[trace_idx] = predecessor[trace_idx] 
       trace_idx=predecessor_v[trace_idx] 
     elif j > 0: 
      ## It's better to extend an existing V 
      predecessor_v[i] = head_v[j - 1] 

     ## Find j such that: seq[head[j - 1]] < seq[i] <= seq[head[j]] 
     ## seq[head[j]] is increasing, so use binary search. 
     j = bisect_left([seq[head[idx]] for idx in xrange(len(head))], seq[i]) 

     if j == len(head): 
      head.append(i) ## no way to turn any increasing seq into a V! 
     if seq[i] < seq[head[j]]: 
      head[j] = i 

     if j > 0: predecessor[i] = head[j - 1] 

    ## trace subsequence back to output 
    result = [] 
    trace_idx = head_v[-1] 
    while (trace_idx >= 0): 
     result.append(seq[trace_idx]) 
     trace_idx = predecessor_v[trace_idx] 

    return result[::-1] 

कुछ उदाहरण उत्पादन:

>>> l1 
[26, 92, 36, 61, 91, 93, 98, 58, 75, 48, 8, 10, 58, 7, 95] 
>>> Vsequence(l1) 
[26, 36, 61, 91, 93, 98, 75, 48, 10, 7] 
>>> 
>>> l2 
[20, 66, 53, 4, 52, 30, 21, 67, 16, 48, 99, 90, 30, 85, 34, 60, 15, 30, 61, 4] 
>>> Vsequence(l2) 
[4, 16, 48, 99, 90, 85, 60, 30, 4] 
संबंधित मुद्दे