这里包含了三种求得递增子序列的算法。
是以前写的代码,这里就拖过来了。
import java.util.ArrayList;
import java.util.Collections;
public class LIS {
public static void LIS(int[] L) { // 时间复杂度为O(n^3)
Long sTime = System.nanoTime();
int n = L.length;
int[] A = new int[n];// 用于存放前i个数值中的递增子序列数值个数;
A[0] = 1;// 以第a1为末元素的最长递增子序列长度为1;
ArrayList a[] = new ArrayList[L.length];// 存放对应的子序列
for (int i = 0; i < L.length; i++) {
a[i] = new ArrayList();
a[i].add(L[i]);
}
for (int i = 1; i < n; i++)// 循环n-1次
{
A[i] = 1;
for (int j = 0; j < i; j++)// 循环i 次
{
if (L[j] < L[i] && A[j] > A[i] - 1) {
A[i] = A[j] + 1;
while (a[i].size() != 0) {// 最多i次
a[i].remove(0);
}
if (a[j].size() != 0) {
for (int k = 0; k < a[j].size(); k++)
// 最多i次
a[i].add(a[j].get(k));
}
a[i].add(L[i]);
}
}
}
int max = 1, tag = 0; // 找到对应的最长长度和对应的子序列数组链表a[tag]
for (int i = 0; i < n; i++) {
if (A[i] > max) {
max = A[i];
tag = i;
}
}
System.out.print("LIS最长递增子序列长度为:" + max + " ");
System.out.println("LIS最长递增子序列为:");
// System.out.println(a[tag]);
Long eTime = System.nanoTime();
System.out.println("该LIS用时:" + (eTime - sTime) + "纳秒");
}
public static void LCSImproveLIS(int[] L) { // 寻找公共子序列法 O(n^2)
Long sTime = System.nanoTime();
int n = L.length;
int[] Temp = new int[n];// 数组B;
for (int i = 0; i < n; i++)
Temp[i] = L[i];
ShellSort(Temp);
int[][] opt = new int[n + 1][n + 1];
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < n + 1; j++)
opt[i][j] = 0;
for (int i = n - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
if (L[i] == Temp[j])
opt[i][j] = opt[i + 1][j + 1] + 1;
else
opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]);
}
}
System.out.println();
System.out.print("LCSImproveLIS最长递增子序列长度为:" + opt[0][0] + " ");
System.out.println("LCSImproveLIS最长递增子序列为:");
int i = 0, j = 0;
while (i < n && j < n) {
if (L[i] == Temp[j]) {
// System.out.print(L[i]+",");
i++;
j++;
} else if (opt[i + 1][j] > opt[i][j + 1])
i++;
else
j++;
}
System.out.println();
Long eTime = System.nanoTime();
System.out.println("该LCSImproveLIS用时:" + (eTime - sTime) + "纳秒");
}
public static void ShellSort(int[] x) {
for (int i = x.length / 2; i > 2; i /= 2) {
for (int j = 0; j < i; j++)
insertSort(x, j, i);
}
insertSort(x, 0, 1);
}
public static void insertSort(int[] x, int start, int incr) {
int temp;
for (int i = start + incr; i < x.length; i += incr) {
for (int j = i; (j >= incr) && (x[j] < x[j - incr]); j -= incr) {
temp = x[j];
x[j] = x[j - incr];
x[j - incr] = temp;
}
}
}
public static void ImproveLIS(int[] L) { // 性能可以达到O(nlogn)
Long sTime = System.nanoTime();
int n = L.length;
int[] Temp = new int[n + 1];// 数组B;
Temp[0] = 0; // 取比较最小值0做基准
Temp[1] = L[0]; // 起始时,起始元素为L[0]
int ltag, rtag, middle; // 分别为二分查找的上界,下界和中点;
ArrayList arr = new ArrayList();
arr.add(Temp[1]);
int max = 1; // max为最长递增子序列长度 初始化为1;
int k = 0;
// 如果arr中的最后一个元素与Temp中最后一个非0元素不一致 则更改arr中的值最多更改N<n个值
for (int i = 1; i < n; i++) {
ltag = 0;
rtag = max;
while (ltag <= rtag)// 二分查找最末元素小于L[i]的长度最大的最大递增子序列;
{
middle = (ltag + rtag) / 2;
if (Temp[middle] < L[i])
ltag = middle + 1;
else
rtag = middle - 1;
}
Temp[ltag] = L[i];// 将长度为p的最大递增子序列的当前最末元素置为ai+1;
if (ltag == max) {
k = max - 1;
// System.out.println((Integer)arr.get(k));
while ((k >= 0) && ((Integer) arr.get(k) != Temp[k + 1])) {
arr.set(k, Temp[k + 1]);
k--;
}
}
if (ltag > max) {
max++;
arr.add(Temp[ltag]);
}
}
System.out.print("ImproveLIS最长递增子序列长度为:" + max + " ");
System.out.println("ImproveLIS最长递增子序列为:");
// System.out.println(arr);
Long eTime = System.nanoTime();
System.out.println("该ImproveLIS用时:" + (eTime - sTime) + "纳秒");
}
public static int[] random(int n) { // 生成n个不同数值的随机数组
int a[] = new int[n];
ArrayList arrlist = new ArrayList();
for (int i = 0; i < a.length; i++)
arrlist.add(i + 1);
for (int i = 0; i < a.length; i++) {
int temp = (int) (Math.random() * arrlist.size());
int data = (Integer) arrlist.remove(temp);
a[i] = data;
}
return a;
}
public static void main(String args[]) {
int a[], b[], c[], d[];
d = random(10);
int n;
System.out.println("10个随机自然数时");
for (int i = 0; i < d.length; i++)
System.out.print(d[i] + " ");
System.out.println();
LIS(d);
LCSImproveLIS(d);
ImproveLIS(d);
System.out.println("1000个随机自然数时");
a = random(1000);
LIS(a);
LCSImproveLIS(a);
ImproveLIS(a);
System.out.println("3000个随机自然数时");
b = random(3000);
LIS(b);
LCSImproveLIS(b);
ImproveLIS(b);
System.out.println("10000个随机自然数时");
c = random(10000);
LIS(c);
LCSImproveLIS(c);
ImproveLIS(c);
}
}