3

The problem here is to find the length of longest subsequence from the input array such that all the elements are in sorted order.

Example: input => [10,22,9,33,21,50,41,60,80]

Example: Output => [10,22,33,50,60,80] is 6

My attempt:

def longest_sequence(input):
    obj = []
    for x in sorted(input):
        obj.append(x)
    print[obj, len(obj)]
    # [[9, 10, 21, 22, 33, 41, 50, 60, 80], 9]

longest_sequence([10,22,9,33,21,50,41,60,80])
Chris vCB
  • 1,023
  • 3
  • 13
  • 28
ajknzhol
  • 6,322
  • 13
  • 45
  • 72
  • [Wikipedia](http://en.wikipedia.org/wiki/Longest_increasing_subsequence) has an article on the problem, including an efficient algorithm to solve it. It might be difficult to understand the explanation, though. – user2357112 Jan 11 '14 at 08:56

2 Answers2

1
import bisect

def lis(xs):
    ret = []
    for x in xs:
        i = bisect.bisect_left(ret, x)
        ret[i:i+1] = x,
    return len(ret)

Example:

>>> lis([10, 1, 2, 3])
3
>>> lis([10,22,9,33,21,50,41,60,80])
6

NOTE In the above code,ret does not contains valid subsequence. But the length is correct. Use the above code what you want is only the length of the LIS.

Explanation:

Think about [10,22,9,11]. There could be two LIS: [10,22], [9,11]. The ret in the above lis function maintains the following condition:

  • ret is sorted; can use binary search (bisect.bisect_left)
  • ret[i] contains the minimum last value for length-i subsequence.
  • ret changes as... (given [10,22,9,11] as input)
    • [10] - after processing the 1st element
    • [10, 22] - after processing the 2nd element
    • [9, 22] - ... Now the minimum value for 1-length subsequence is 9! 10 is overwritten.
    • [9, 11]

Time complexity: O(nk) where n is the number of list item, k is the length of the LIS.

UPDATE

Modified version that correctly get the subsequence:

import bisect

def lis(xs):
    if not xs: return []
    prev = {}
    ret = []
    for x in xs:
        i = bisect.bisect_left(ret, x)
        ret[i:i+1] = x,
        prev[x] = ret[i-1] if i > 0 else None
    subseq = [ret[-1]]
    while subseq[-1] is not None:
        subseq.append(prev[subseq[-1]])
    return list(reversed(subseq[:-1]))

Example:

>>> lis([])
[]
>>> lis([10, 1, 2, 3])
[1, 2, 3]
>>> lis([10,22,9,33,21,50,41,60,80])
[10, 22, 33, 41, 60, 80]
>>> lis([1,5,2,6,3,4])
[1, 2, 3, 4]
>>> lis([100,200,1,2,3])
[1, 2, 3]
falsetru
  • 357,413
  • 63
  • 732
  • 636
-1
data = [100,1,2,3]

conformed = []

for i in range (0, len(data)):
   if i == 0:
      if data[1]<data[0]:
         conformed.append(data[1])
      else:
         conformed.append(data[0])
   else:
       if data[i] > data[i-1]:
          conformed.append(data[i])

print conformed, len(conformed)
Chris vCB
  • 1,023
  • 3
  • 13
  • 28