问题描述
求一个数组的最长递减子序列比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}。
问题分析
本问题类似编程之美中的求数组中最长递增子序列问题。可以利用动态规划方法解决。
假设在目标数组array[]的前i个元素中,最长递减子序列的长度为LDS[i]。那么
LDS[i+1] = max{1,LDS[k]+1},其中array[i+1]<array[k],for any k<=i。
即如果array[i+1]<array[k],那么第i+1个元素可以添加到LDS[k]长的子序列后构成一个更长的递减子序列。与此同时,
array[i+1]可以由自身构造成一个长度为1的子序列。
所以代码清单为:
for (int i = 0; i < len; i++) { LDS[i] = 1; for (int k = 0; k < i; k++) { // LDS[i+1]=max{1,LDS[k]+1}, array[i+1]<array[k],for any k<=i; if (array[i] < array[k] && LDS[k] + 1 > LDS[i]) { LDS[i] = LDS[k] + 1; } } }
在获取到LDS数组后,遍历数组,获取构成最长递减子序列的元素。
print(int[] array, int[] lds, int max, int end) { if (max == 0) return; int i = end; while (lds[i] != max) i--; print(array, lds, max - 1, i - 1); System.out.print(array[i] + ""); }
实现代码
class LDSProblem {
int[] array) {
// 数组array中的前i个元素中,最长递减子序列的长度是LDS[i]
int len = array.length;
int[len];
int max = 0;
int i = 0; i < len; i++) {
8: LDS[i] = 1;
int k = 0; k < i; k++) {
// LDS[i+1]=max{1,LDS[k]+1}, array[i+1]<array[k],for any k<=i;
if (array[i] < array[k] && LDS[k] + 1 > LDS[i]) {
12: LDS[i] = LDS[k] + 1;
13: }
14: }
15: }
16: max = maxsub(LDS);
+ max);
);
19: print(LDS);
);
21: print(array, LDS, max, len - 1);
22: }
23:
// max:最长子序列长度
// end:最长递减子序列中的最后一个元素
// lds:数组array中的前i个元素中,最长递减子序列的长度数组
int end) {
if (max == 0)
return;
int i = end;
while (lds[i] != max)
32: i--;
33: print(array, lds, max - 1, i - 1);
);
35: }
36:
int[] array) {
int i = 0; i < array.length; i++) {
);
40: }
41: System.out.println();
42: }
43:
int[] LDS) {
int m = 0;
int i = 0; i < LDS.length; i++) {
if (LDS[i] > m)
48: m = LDS[i];
49: }
return m;
51: }
52:
void main(String[] args) {
int[] { 9, 4, 3, 2, 5, 4, 3, 2 };
print(array);*/
57: maxSubstrDecrease(array);
58: }
59: }