Question 6 Longest Increasing Subsequence母体

Method 1暴力解(从后往前,但是不会用在面试中,只是为了训练)

public int longest(int[] array) {
    // assume array valid
    int[] longest = new int[]{1};
    int currentLength = 0;
    dfs(longest, currentLength, array, array.length - 1, null);
    return longest[0];
}
private void DFS(int[] longest, int currentLength, int[] array, int index, Integer lastAddedValue) {
    // 哪里都是解
    longest[0] = Math.max(longest[0], currentLength);
    
    // branch 所有在index之前比加过的第一个元素还要小的元素,我要知道上次加了谁?
    for (int i = index; i >= 0; i++) {
        if (lastAddedValue == null || array[i] < lastAddedValue) {
            dfs(longest, currentLength + 1, array, array.length - 1, array[i]);
        }
    }
}

从所有解的角度来衡量:dfs走的每一条路都是不一样,没有任何了一步计算的path

只说剪枝(我这啊哦这条路最终的答案肯定是不hi我要的,那我就压根不去)

去重:我这条路以前已经走过了,答案我知道了,现在不想再走一遍了

Method 2 从backtracking 到pure recursion

看到重复的input size recursion call

  • 在1,2,3都调用了pureRecursion(array,4)input size一样,都是4

  • 答案一定都是一样的==》产生了重复&没有必要的运算

  • pure recursion里的input一样,结果一样,就是完全一样的问题

Method 3 从pure recursion to recursion memo

既然以某个index为开始的LIS一定永远都不会改变==》 那么我们以每一个starting index为开始的LIS只需要计算一次

Longest Increating Subsequence时间复杂度是多少?O(N!)==> O(N^2)

Method 4真的确定有优化, pure recursion memo to dynamic programming

顺序又回到了ending index上:linear scan回头看

Step1 DP definition

  • LIS[i] represent longest increasing subsequence ending at i must including i

Step 2 Base Case

  • LIS[0] = 1

Step 3 Induction Rule

  • LIS[i] = Max(LIS[j] + 1) iff j < i && array[j] < array[i]

Step 4 Fill in order

  • left to right

Step 5 Return what

  • globalMax of all LIS[i]

TC & SC: O(n^2), O(n)

Last updated