使用递归找到所有可能的最长增长子序列

时间:2014-02-15 11:37:43

标签: java algorithm backtracking lis recursive-backtracking

我试图使用递归找到所有可能增长最长的子序列。当我尝试输入数组{10,22,9,33,21,50,41,40,60,55}时,它工作正常,输出为:

10 22 33 40 55 /
10 22 33 41 55 /
10 22 33 50 55 /
10 22 33 40 60 /
10 22 33 41 60 /
10 22 33 50 60 /

但是当我尝试输入数组{2,-3,4,90,-2,-1,-10,-9,-8}时,我得到了一个输出:

-3 4 90 /
-3 -2 -1 /
-10 -9 -8 /

在这种情况下,我没有得到2 4 90。我应该在代码中更改哪些内容以使其适用于此案例?

public class Main {
    public static void main(String[] args) {
        int arr[]={10,22,9,33,21,50,41,40,60,55};
        int lis[]=new int[arr.length];
        for(int i=0;i<arr.length;i++){
            lis[i]=1;
        }
        for(int i=1;i<arr.length;i++){
            for(int j=0;j<i;j++){
                if(arr[i]>arr[j]&&lis[i]<lis[j]+1){
                    lis[i]=lis[j]+1;
                }
            }
        }
        int max=0;
        for(int i=0;i<arr.length;i++){
            if(max<lis[i])
                max=lis[i];
        }
        //**************Recursive Print LIS****************
        int rIndex=-1;
        for(int i=arr.length-1;i>=0;i--){
            if(lis[i]==max){
                 rIndex=i;
                 break;
            }
        }
        int res[]=new int[max];
        printLISRecursive(arr,rIndex,lis,res,max,max);
    }

    private static void printLISRecursive(int[] arr, int maxIndex, int[] lis, int[] res, int i, int max) {
        if(maxIndex<0)return;
        if(max==1&&lis[maxIndex]==1&&i==1){
            res[i-1]=arr[maxIndex];
//            System.out.println("Using Print Recursion:");
            for(int j=0;j<res.length;j++){
                System.out.print(res[j]+" ");
            }
            System.out.println();
            return;
        }
        if(lis[maxIndex]==max){
            res[i-1]=arr[maxIndex];
            printLISRecursive(arr, maxIndex-1, lis, res, i-1, max-1);
        }
        printLISRecursive(arr, maxIndex-1, lis, res, i, max);
    }

}

3 个答案:

答案 0 :(得分:2)

public static String  lcs(String  a, String  b){
    int aLen = a.length();
    int bLen = b.length();
    if(aLen == 0 || bLen == 0){
        return "";
    }else if(a.charAt(aLen-1) == b.charAt(bLen-1)){
        return lcs(a.substring(0,aLen-1),b.substring(0,bLen-1))
            + a.charAt(aLen-1);
    }else{
        String  x = lcs(a, b.substring(0,bLen-1));
        String  y = lcs(a.substring(0,aLen-1), b);
        return (x.length() > y.length()) ? x : y;
    }
}

答案 1 :(得分:1)

public static int lcsrec(String x, String y) {

    // If one of the strings has one character, search for that character
    // in the other string and return the appropriate answer.
    if (x.length() == 1) 
      return find(x.charAt(0), y);
    if (y.length() == 1)
      return find(y.charAt(0), x);

    // Solve the problem recursively.

    // Corresponding beginning characters match.
    if (x.charAt(0) == y.charAt(0))
      return 1+lcsrec(x.substring(1), y.substring(1));

    // Corresponding characters do not match.
    else 
      return max(lcsrec(x,y.substring(1)), lcsrec(x.substring(1),y));

  }

答案 2 :(得分:0)

根据您的回溯想法,我编写以下代码。为简单起见,可以删除许多输入参数。

public class LIS {

    private static int[] count;

    public int longestIncreaseSubsequence(int[] seq) {
        int n = seq.length;

        for (int i = 0; i < n; i++) {
            count[i] = 1;
        }

        for (int i = 1; i < n; i++) {
            int max = 0;
            for (int j = i-1; j >= 0; j--) {
                if (seq[j] < seq[i]) max = Math.max(max, count[j]);
            }
            count[i] = max + 1;
        }

        int max = Integer.MIN_VALUE;
        for (int i = 0; i < count.length; i++) {
            if (count[i] > max) max = count[i];
        }

        return max;
    }

    public void printLIS(int[] a, int k, int[] count, int[] arr, int max) {
        if (k == max) {
            for (int i = max; i >= 1; i--) {
                System.out.printf("%d ", arr[a[i]]);
            }
            System.out.println();
        } else {
            k++;

            int[] candidates = new int[arr.length];
            int ncandidate = 0;

            for (int i = a[k-1]; i >= 0; i--) {
                if (count[i] == max-k+1 && (arr[i] < arr[a[k-1]] || count[i] == max)) {
                    candidates[ncandidate] = i;
                    ncandidate++;
                }
            }

            for (int i = 0; i < ncandidate; i++) {
                a[k] = candidates[i];
                printLIS(a, k, count, arr, max);
            }
        }
    }

    public static void main(String[] args) {
        int[] input = {2,-3,4,90,-2,-1,-10,-9,-8};
        LIS lis = new LIS();

        count = new int[input.length];  

        int max = lis.longestIncreaseSubsequence(input);

        int[] a = new int[max+1];
        a[0] = input.length-1; 

        lis.printLIS(a, 0, count, input, max);
    }
}