您的位置:首页 > 其它

最长不下降子序列

2015-09-20 16:21 176 查看
package dp;

import java.util.Arrays;

/***
* [3,4,7,1,9] 的最长不减序列是[3,4,7,9]。返回4。
*
* @author MiXian
*
*/
public class LongestNoDecreaseSubArray {

/**
* O(n^2)
*/
public static int length(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}

int l = nums.length;
int[] dp = new int[l];
int max = 1;
Arrays.fill(dp, 1);
for (int i = 1; i < l; ++i) {
int n = nums[i];
for (int j = i - 1; j >= 0; --j) {
if (nums[j] <= n && dp[j] >= dp[i]) {
dp[i] = dp[j] + 1;
if (dp[i] > max) {
max = dp[i];
}
}
}
}
return max;
}

/**
* O(nlogn)的算法关键是它建立了一个数组b[],b[i]表示长度为i的不下降序列中结尾元素的最小值
* K表示数组目前的长度,算法完成后K的值即为最长不下降子序列的长度。
*
* 具体点来讲:
*
* 设当前的以求出的长度为K,则判断a[i]和b[k]:
*
* 1.如果a[i]>=b[k],即a[i]大于长度为K的序列中的最后一个元素,这样就可以使序列的长度增加1,即K=K+1,
* 然后现在的b[k]=a[i]
*
* 2.如果a[i]<b[k],那么就在b[1]...b[k]中找到最大的j,使得b[j]<a[i],然后因为b[j]<a[i],
* 所以a[i]大于长度为j的序列的最后一个元素,那么就可以更新长度为j+1的序列的最后一个元素,即b[j+1]=a[i]。
*
* 算法复杂度的分析:
*
* 因为共有n个元素要进行计算;每次计算又要查找n次,所以复杂度是O(n^2),但是,注意到b[]数组里的元素的单调递增的,所以我们可以用二分法,
* 查找变成了logn次.
* 这样算法的复杂度就变成了O(nlogn)。
*/
public static int len(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}

int l = nums.length;
int[] lastOfLen = new int[l];
int curLen = 0;
lastOfLen[0] = nums[0];// 长度为1寸在lastOfLen[0]中
for (int i = 1; i < l; ++i) {
if (nums[i] >= lastOfLen[curLen]) {
lastOfLen[++curLen] = nums[i];
} else {
if (nums[i] < lastOfLen[0]) {
lastOfLen[0] = nums[i];
} else {
lastOfLen[findLen(lastOfLen, 0, curLen, nums[i])] = nums[i];
}
}
}
return 1 + curLen;
}

// 将n应该更新的下面返回   n属于[lens[0], lens[r])
private static int findLen(int[] lens, int l, int r, int n) {
while (l < r) {
int m = (l + r) >> 1;
if (n >= lens[m] && n < lens[m + 1]) {
return m + 1;
} else if (n < lens[m]) {
r = m;
} else {
l = m + 1;
}
}
return l;
}

public static void main(String[] args) {
System.out.println(length(new int[] { 3, 4, 7, 9 }));
System.out.println(length(new int[] { 3, 4, 1, 7, 9 }));
System.out.println(length(new int[] { 3, 4, 8, 7, 9 }));
System.out.println(length(new int[] { 3, 1, 7, 9 }));
System.out.println(length(new int[] { 3 }));
System.out.println(length(new int[] { 3, 2, 2, 1 }));
System.out.println(length(new int[] { 1, 1, 2 }));

System.out.println(len(new int[] { 3, 4, 7, 9 }));
System.out.println(len(new int[] { 3, 4, 1, 7, 9 }));
System.out.println(len(new int[] { 3, 4, 8, 7, 9 }));
System.out.println(len(new int[] { 3, 1, 7, 9 }));
System.out.println(len(new int[] { 3 }));
System.out.println(len(new int[] { 3, 2, 2, 1 }));
System.out.println(len(new int[] { 1, 1, 2 }));
boolean isTest = true;
if (isTest) {
int[] lens1 = { 3, 4, 9 };
test(lens1, 3);
test(lens1, 4);
test(lens1, 5);

int[] lens3 = { 1, 5 };
test(lens3, 4);
test(lens3, 1);
}
}

// /////////////////// tests
private static void test(int[] lens, int n) {
for (int i = 0; i < lens.length; ++i) {
System.out.print(lens[i] + " ");
}
System.out.println(" : " + n);
System.out.println(findLen(lens, 0, lens.length - 1, n));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: