Skip to content

动态规划问题——最长上升子序列(LIS)(一)

题目

样本代码时间复杂度为〇(n²)

如:求 2 7 1 5 6 4 3 8 9 的最长上升子序列。我们定义d(i) (i∈[1,n])来表示前i个数以A[i]结尾的最长上升子序列长度。

  • 前1个数 d(1)=1 子序列为2;
  • 前2个数 7前面有2小于7 d(2)=d(1)+1=2 子序列为2 7
  • 前3个数 在1前面没有比1更小的,1自身组成长度为1的子序列 d(3)=1 子序列为1
  • 前4个数 5前面有2小于5 d(4)=d(1)+1=2 子序列为2 5
  • 前5个数 6前面有2 5小于6 d(5)=d(4)+1=3 子序列为2 5 6
  • 前6个数 4前面有2小于4 d(6)=d(1)+1=2 子序列为2 4
  • 前7个数 3前面有2小于3 d(3)=d(1)+1=2 子序列为2 3
  • 前8个数 8前面有2 5 6小于8 d(8)=d(5)+1=4 子序列为2 5 6 8
  • 前9个数 9前面有2 5 6 8小于9 d(9)=d(8)+1=5 子序列为2 5 6 8 9
  • d(i)=max{d(1),d(2),……,d(i)} 我们可以看出这9个数的LIS为d(9)=5

Java代码

java
public class Main {
    int LIS(int A[], int n) {
        int d[] = new int[n];
        int len = 1;
        int i, j;
        for (i = 0; i < n; i++) {
            d[i] = 1;
            for (j = 0; j < i; j++) {
                // 当前的位置的数与之前的数比较,如果数列是上升的,且序列长度+1比当前序列长度大或相等
                if (A[j] <= A[i] && (d[j] + 1) >= d[i])
                    //使这个数之前的最大长度加1(最长上升序列加上这个数)
                    d[i] = d[j] + 1;
            }
            // 把当前d[i]的最大长度赋值给len
            if (d[i] > len)
                len = d[i];
        }
        // 返回最长上升子序列的长度
        return len;
    }

    public static void main(String[] args) {
        int A[] = {2, 7, 1, 5, 6, 4, 3, 8, 9};
        int n = A.length;
        Main test = new Main();
        int count = test.LIS(A, n);
        System.out.println(count);
    }
}

运行结果

5

Python代码

python
# 第一种写法
def longestIncreasingSubsequence(nums, length):
    # 如果列表为空或者列表长度为0就直接返回0
    if nums == None or len(nums) == 0:
        return 0
    # 初始化列表为length个0,用来记录到当前位置的最长升序序列的长度
    sublongest = [0 for i in range(length)]
    sublongest[0] = 1
    longest = 0
    for i in range(1, length):
        sublong = 0
        for j in range(0, i):
            # 如果当前元素比前面的元素大
            if nums[j] <= nums[i]:
                # 则将前面元素的最长序列和当前的最长序列比较大小,把大的赋值给sublong
                sublong = max(sublongest[j], sublong)
        # 加上到自身位置那个元素
        sublongest[i] = sublong + 1
        # 比较长度列表末尾的元素和longest的大小,把两者大的赋值给longest
        longest = max(sublongest[i], longest)
    return longest

# 第二种写法
def longestIncreasingSubsequence2(Testarray, num):
    d = [0 for i in range(num)]
    longest = 1
    for i in range(num):
        d[i] = 1
        for j in range(i):
            if (Testarray[j] <= Testarray[i]) and (d[j] + 1) >= d[i]:
                d[i] = d[j] + 1
        if d[i] > longest:
            longest = d[i]
    return longest


if '__name__ = __main__':
    a = [2, 7, 1, 5, 6, 4, 3, 8, 9]
    # count = longestIncreasingSubsequence(a,len(a))
    count = longestIncreasingSubsequence2(a, len(a))
    print(count)

运行结果

5