【算法题】寻找最长不下降序列
题目:
设有n个不同相同的整数组成的数列,记为b(1),b(2),b(3),...,b(n),i 表示元素所在位置,若存在 i1 < i2 < i3 <...< ie,且有 b(i1) <b(i2) < b(i3) <...< b(ie),那么称长度为e的不下降序列。
例如:序列 [13, 7, 9, 16, 38, 24, 37, 18, 44, 19, 21, 22, 63, 15],存在多个不下降序列:
长度为 1 的不下降序列【63】,【15】
长度为 2 的不下降序列【44,63】,【22,63】
长度为 3 的不下降序列【38,44,63】,【37,44,63】,【21,22,63】
长度为 4 的不下降序列【24,37,44,63】,【19,21,22,63】
长度为 5 的不下降序列【18,19,21,22,63】
长度为 6 的不下降序列【16,18,19,21,22,63】
长度为 7 的不下降序列【9,16,18,19,21,22,63】
长度为 8 的不下降序列【7,9,16,18,19,21,22,63】
需要找出其中最长的不下降序列。
算法思路:
使用动态规划,逆向推。从序列的末尾查找,记录下以当前元素为起始,可以找到的不下降序列,并且记录下序列中的下一个元素。
数据结构:b[n][3] 表示的意思:
b[i][1] 表示第i个元素本身;
b[i][2] 表示第i个元素为起点,后续序列组成的最长不下降子序列长度;
b[i][3] 指向下一个不下降元素
int n; int b[][]; public void find() { for (int i = n - 1; i >= 1; i--) { int maxLen = 0; // 找到后面序列中最长的不下降序列长度数 int next = 0; // 记录下拥有最长不下降序列长度所在的元素 for (int j = i + 1; j <= n; j++) { if ((b[j][1] > b[i][1]) && (b[j][2] > maxLen)) { maxLen = b[j][2]; next = j; } } b[i][2] = maxLen + 1; // 不降序长度加1 b[i][3] = next; // 当前元素的后继指向找到的具有最大不降序长度的元素 } output(); // 输出序列 } public void output() { int point = 1; // 寻找最大长度所对应的起始元素 for (int i = 2; i <= n; i++) { if (b[i][2] > b[point][2]) { point = i; } } System.out.println("max length is :" + b[point][2]); while (point != 0) { System.out.print("\t" + b[point][1]); point = b[point][3]; } } @Test public void test01() { int[] serial = {13, 7, 9, 16, 38, 24, 37, 18, 44, 19, 21, 22, 63, 15}; n = serial.length; b = new int[n + 1][n + 1]; for (int i = 1; i <= n; i++) { // 初始化 b[i][1] = serial[i - 1]; b[i][2] = 1; b[i][3] = 0; } find(); }