最长的子序列2d

时间:2015-10-15 20:17:50

标签: algorithm subsequence

我按照固定顺序对 m 整数排序 n 。我需要找到一个增长最长的子序列,这样子序列中的每个元素都属于一个数组。我能做的比 O (n 2 )好吗?

2 个答案:

答案 0 :(得分:1)

与@svs一致,这不可能在小于O(m * n)的情况下实现。但是,在实践中,一旦您知道无法在其中找到更长的子序列,就可以通过终止迭代来减少平均最差时间。

琐碎的循环:

maxList = []
for arr in arrays:
    last = arr[0] - 1
    tempList = []
    for element in arr:
        if element > last:
            tempList.append(element)
            if len(tempList) > len(maxList):
                    maxList = tempList

        else:
            tempList = [element]
        last = element

return (maxList, iters)

忽略冗余循环迭代:

maxList = []
for arr in arrays:
    if len(maxList) == len(arr):
        break

    last = arr[0] - 1
    tempList = []
    for (index, element) in enumerate(arr):
        if element > last:
            tempList.append(element)
            if len(tempList) > len(maxList):
                    maxList = tempList[:]
        else:
            tempList = [element]

        # if continuing looking down the array could not result in a longer
        # increasing sequence
        if (len(tempList) + (len(arr) - (index + 1)) <= len(maxList)):
            break

        last = element

return (maxList, iters)

答案 1 :(得分:0)

是的,可以通过动态编程和备注来完成...复杂度为O(n Log(base2)n)别名O(nLogn)。为了证明这一点,我使用了一个外部静态复杂度变量(称为complexity),并在每次递归迭代中递增,以表明复杂度将为O(nLogn)-

package com.company.dynamicProgramming;

import java.util.HashMap;
import java.util.Map;

public class LongestIncreasingSequence {

    static int complexity = 0;    // <-- here it is init to 0

    public static void main(String ...args){


        int[] arr = {10, 22, 9, 33, 21, 50, 41, 60, 80};
        int n = arr.length;

        Map<Integer, Integer> memo = new HashMap<>();

        lis(arr, n, memo);

        //Display Code Begins
        int x = 0;
        System.out.format("Longest Increasing Sub-Sequence with size %S is -> ",memo.get(n));
        for(Map.Entry e : memo.entrySet()){

            if((Integer)e.getValue() > x){
                System.out.print(arr[(Integer)e.getKey()-1] + " ");
                x++;
            }
        }
        System.out.format("%nAnd Time Complexity for Array size %S is just %S ", arr.length, complexity );
        System.out.format( "%nWhich is equivalent to O(n Log n) i.e. %SLog(base2)%S is %S",arr.length,arr.length, arr.length * Math.ceil(Math.log(arr.length)/Math.log(2)));
        //Display Code Ends

    }



    static int lis(int[] arr, int n, Map<Integer, Integer> memo){

        if(n==1){
            memo.put(1, 1);
            return 1;
        }

        int lisAti;
        int lisAtn = 1;

        for(int i = 1; i < n; i++){
            complexity++;                // <------ here it is incremented to cover iteration as well as recursion..

            if(memo.get(i)!=null){
                lisAti = memo.get(i);
            }else {
                lisAti = lis(arr, i, memo);
            }

            if(arr[i-1] < arr[n-1] && lisAti +1 > lisAtn){
                lisAtn = lisAti +1;
            }
        }

        memo.put(n, lisAtn);
        return lisAtn;

    }
}

您尝试运行它并查看时间复杂度的值(源自可变复杂度)-

Longest Increasing Sub-Sequence with size 6 is -> 10 22 33 50 60 80 
And Time Complexity for Array size 9 is just 36 
Which is equivalent to O(n Log n) i.e. 9Log(base2)9 is 36.0
Process finished with exit code 0
关键是,在每次递归中,我们都会计算第ith个索引的LIS并将其存储在备忘录映射中。此外,当我们处于第(i + 1)次迭代时-由于备忘图的可用性,我们不需要重新计算(递归)整个0到ith索引,并且将复杂度从指数级降低到了nlogn级。