求解最長遞增子序列的長度

一、問題描述

給定一個序列,求最長遞增子序列的長度。比如: arr[] = {1,4,1,5,9,2,6,5}   的最長遞增子序列長度爲4。即爲:1,4,5,9

 

二、算法分析

方法1、解決這個問題,可以想到求解最長公共子序列問題,把數組arr[]按照從小到大的順序排序,得到另一個數組b[],然後求解arr和b的最長公共子序列長度,就是上述問題的解。解決LCS問題的時間複雜度爲O(N^2),排序時間複雜度O(NlogN),故整個算法的時間複雜度爲O(N^2),空間複雜度爲O(N),

 方法2、直接用DP求解,算法時間複雜度爲O(N^2)  (當然LCS也是利用了DP,但是還是得先進行排序,然後才進行DP)

下面進行分析,要求最長遞增子序列,可知,最長遞增子序列的子序列必定也是對應序列的最長子序列(可能有點繞,但是學習或者瞭解動態規劃的同學,應該不難理解)所以就有了最優子問題

(1)最優子問題

設lis[i] 表示索引爲 [0...i] 上的數組上的 最長遞增子序列。初始時,lis[i]=1(即初始值爲1,這樣應該不需要解釋,一個序列的最長遞增子序列最少也得有一個嘛)下面就是遞推公式

當 arr[i] > arr[j],lis[i] = max{lis[j]}+1 ;其中,j 的取值範圍爲:0,1...i-1

當 arr[i] < arr[j],lis[i] = max{lis[j]} ;其中,j 的取值範圍爲:0,1...i-1

 



2.1、代碼實現

public class LIS {
    public static int lis(int[] arr){
        if(arr == null || arr.length == 0)
            return 0;
        return lis(arr, arr.length);
    }
    
    private static int lis(int[] arr, int length){
        int lis[] = new int[length];
        
        for(int i = 0; i < length; i++)
            lis[i] = 1;
        
        for(int i = 1; i < length; i++)
        {
            for(int j = 0; j < i; j++)
            {
                if(arr[i] > arr[j] && lis[j] + 1 > lis[i])
                    lis[i] = lis[j] + 1;
            }
        }
        
        int max = lis[0];
        for(int i = 1; i < length; i++)
            if(max < lis[i])
                max = lis[i];
        return max;
    }
    
    public static void main(String[] args) {
        int[] arr = {1,4,1,5,9,2,6,5};
        int result = lis(arr);
        System.out.println(result);
    }
}











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章