Longest Increasing Subsequence Review

Let A[1...n] be a sequence of distinct integers. An increasing subsequence (IS) of A is a subsequence A[i1], A[i2], ..., A[ik], with i1 < i2 < ... < ik, such that, for is < it, we have A[is] < A[it]. A longest increasing subsequence (LIS) of A is an increasing subsequence of maximum length.

Problem: Find the length of LIS of A

We start with a solution using dynamic programming.

let F[i] be the length of LIS of A[1...i].
let G[i] be the maximum length of IS ending with A[i].

Then we have the following state-transition equations:

G[i] = max{ G[j] + 1 } for all 1 <= j < i with A[i] > A[j]
       or 1 if such a j does not exist

F[i] = max{ G[j] } for all 1 <= j <= i

It is obvious that the running time of this algorithm is O(n^2).

Can we do better? Definitely!

Let B[i] be the last element of a minimum LIS of length i. A minimum LIS of length i here refers to a LIS which has smallest ending element among all LISes of length i.

We have B[i] < B[i+1] for all 1 <= i < n. (proof by contradiction)

// initialize B
for i from 1 to n
  B[i] = nil

// calculate B
for i from 1 to n
  if there's such a j with 1 <= j < i-1 and B[j] < A[i] < B[j+1]
    B[j+1] = A[i]
  else if A[i] < B[1]
    B[1] = A[i]
  else if A[i] > B[i-1]
    B[i] = A[i]

// find the answer
len = 1
for i from n downto 1
  if B[i] is not nil
    len = i
    break

// then len holds the length of LIS of A.

Using this algorithm, we can find the length of LIS of A in running time of O(nlgn).

Discussion

What if A has duplicate elements ?

The two algorithms above are also correct for solving this case.

What if we want to find the length of longest non-decreasing subsequence of a sequence which may have duplicate elements ?

It is trival to modify the first algorithm to solve this problem, we only need to change transition equation of G[i] to:

G[i] = max{ G[j] + 1 } for all 1 <= j < i with A[i] >= A[j]
       or 1 if such a j does not exist

For the second algorithm, we have property B[i] <= B[i+1] instead of B[i] < B[i+1] in this case. And the calculating process of B should be modified.

// calculate B
for i from 1 to n
  if there's such a j with 1 <= j < i-1 and B[j] <= A[i] < B[j+1]
    B[j+1] = A[i]
  else if A[i] < B[1]
    B[1] = A[i]
  else if A[i] >= B[i-1]
    B[i] = A[i]

 

posted @ 2016-04-30 20:42  william-cheung  阅读(174)  评论(0编辑  收藏  举报