您的位置:首页 > 其它

最长递增子序列

2015-12-02 16:16 351 查看
求一个一维数组中的最长递增子序列的长度

比如,在序列{1, -1, 2, -3, 4, -5, 6, -7}中,其最长的递增子序列为1,2,4,6

思路: 编程之美上的题,也是蛮经典的动态规划题。 思路还是去找规律,我们拿LCS来表示最长递增子序列的长度

第一个数1, 则LCS(1)=1, 因为就一个数嘛

第二个数-1, LCS(1,-1)=1, 因为-1对于1来说不是递增的

第三个数2, LCS(1,-1,2)=2, 因为2对于前两个数是递增的

所以规律是 LCS(i) = if a[i] > a[0...i-1] => max(1, LCS(1...i-1)) + 1 就是如果a[i]的值大于数组下标在0到i-1之间的全部数, 且max(1, LCS(1...i-1))+1>LCS(i)

void findLCS01(int[] array){
int len = array.length;
int[] LIS = new int[len];

for(int i = 0; i < len; i++){
LIS[i] = 1;
for(int j = 0; j<i; j++){
if(array[i] > array[j] && LIS[j] + 1 > LIS[i]){
LIS[i] = LIS[j] + 1;
}
}
}

show(LIS);
}


上述的方法需要嵌套内循环,当遍历到a[i]元素时,需要对0到i-1之间的元素,依次判断是否小于当前a[i]元素,并且找出最大的LCS值,将其加一付给LCS[i], 时间复杂度是o(n^2)

为了降低时间复杂度,编程之美上的解决方法是对i之前的元素进行快速排序,这样就不用每次都去遍历他们,我的想法是,可以增加一个数组max,max[i-1]保存的是从0到i-1之间遇到的最大元素,数组LCS, LCS[i]保存0到i之间的最大值, 这样每次只需比较a[i]与max[i-1]即可, 如果a[i]>max[i-1] 则max[i]=a[i]然后再去判断LCS的值,否则LCS[i]沿用LCS[i-1], max[i]沿用max[i-1]

void findLCS02(int[] array){
int len = array.length;

if(len <= 0) return;
if(len <= 1) return;

int[] LCS = new int[len];
int[] max = new int[len];

LCS[0] = 1;
max[0] = array[0];

for(int i = 1; i < len; i++){
LCS[i] = 1;
if(array[i] > max[i-1]){
max[i] = array[i];
if(LCS[i-1] + 1 > LCS[i]){
LCS[i] = LCS[i-1] + 1;
}
}else{
LCS[i] = LCS[i-1];
           max[i] = max[i-1];
}
}

show(LCS);
}


这样时间复杂度将为o(n), 用空间换时间了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: