最長遞增子串行(longest increasing subsequence) ,我們簡記為 lis。
題:求乙個一維陣列arr[i]中的最長遞增子串行的長度,如在序列1,-1,2,-3,4,-5,6,-7中,最長遞增子串行長度為4,序列為1,2,4,6。
解法一:快速排序+lcs
剛開始做這道題的時候,由於之前做過幾道lcs的題,於是最先想到的是快速排序+lcs的方法。這種方法解決了當時只計算單個case的問題,但是後來面對計算多個 case的問題的時候,第一次遇到memory limit exceeded。於是就意識到這種簡單解法的時間和空間的複雜度都太高了。於是只能另尋他法。
public class main解法三:二分查詢+dp(o(nlogn))public static void qsort(int a,int p,int r)
}
return z[n][n];
}
public static void main(string args) ;
n=arr.length;
a=new int[n+1];
b=new int[n+1];
int i,j;
for(i=1;i<=n;i++)
quicksort(a);
//控制嚴格遞增
for(i=1;i
解法二:dp(o(n^2))
從後向前分析,很容易想到,第i個元素之前的最長遞增子串行的長度要麼是1(單獨成乙個序列),要麼就是第i-1個元素之前的最長遞增子串行加1,可以有狀態方程:
lis[i+1] = max,aray[k],for any k <=i.
即如果array[i+1]大於array[k],那麼第i+1個元素可以接在lis[k]長的子串行後面構成乙個更長的子串行。於此同時array[i+1]本身至少可以構成乙個長度為1的子串行。
public int lis(int arr, int size)}}
}return lis;
}
在解法二中,當考察第i+1個元素的時候,我們是不考慮前面i個元素的分布情況的。現在我們從另乙個角度分析,即當考察第i+1個元素的時候考慮前面i個元素的情況。
目的:我們期望在前i個元素中的所有長度為len的遞增子串行中找到這樣乙個序列,它的最大元素比arr[i+1]小,而且長度要盡量的長,如此,我們只需記錄len長度的遞增子串行中最大元素的最小值就能使得將來的遞增子串行盡量地長。
方法:維護乙個陣列maxv[i],記錄長度為i的遞增子串行中最大元素的最小值,並對於陣列中的每個元素考察其是哪個子串行的最大元素,二分更新
maxv
陣列,最終i的值便是最長遞增子串行的長度。
仔細的分析請看最長遞增子串行 o(nlogn)演算法,
public class lis else}return left;
} static int getlis(int arr, int size)else
}return len;
} /**
* @param args
*/public static void main(string args) ;
/* 計算lis長度 */
system.out.println(getlis(arr,arr.length));
}}
最長遞增子串行 LIS
對於這個問題,最直觀的dp方法是cnt i 表示以height i 結束的最長遞增子串行的元素的個數,遞迴方程是cnt i max for max i 0 i求出整個數列的最長遞增子串行的長度 if b i max max b i cout return 0 顯然,這種方法的時間複雜度仍為o n 2...
最長遞增子串行 LIS
給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為6的陣列a,則其最長的單調遞增子串行為,長度為4.這個問題可以轉換為最長公共子串行問題。如例子中的陣列a,則我們排序該陣列得到陣列a 然後找出陣列a和a 的最長公共子串行即可。顯然這裡最長公共子串行...
最長遞增子串行(LIS)
300.longest increasing subsequence good 給定乙個長度為n的陣列,找出乙個最長的單調遞增子串行 不一定連續,當時先後順序不能亂 更正式的定義是 設l 是n個不同的實數的序列,l的遞增子串行是這樣乙個子串行lin 其中k1。比如陣列a 為,那麼最長遞增子串行為。以...