(動態規劃)最長遞增子序列

問題描述java

給定一個長度爲N的數組,找出一個最長的單調自增子序列(不必定連續,可是順序不能亂)。例如:給定一個長度爲6的數組A{5, 6, 7, 1, 2, 8},則其最長的單調遞增子序列爲{5,6,7,8},長度爲4.數組

方法一:這個方法是我用java實現的,利用java裏 容器,從頭開始遍歷數組,每遍歷一個元素,須要進行兩步操做:第1、建立一個新的LinkedList,並將這個元素放進去;第2、將這個元素分別與以前元素的各個遞增隊列的最大值比較,若是大於以前遞增隊列的最大值,則將其存儲到相應的LinkedList裏。最後的結果是:一共須要n個隊列,這n個隊列裏存儲的是全部的遞增子序列,找到最大的便可。ide

代碼以下:函數

public class MaxLenSubSeq {
    //最長遞增子序列
   public int num[] =new int[100];
   @SuppressWarnings("unchecked")
public LinkedList<Integer> maxLenSubSeq(int[] seq){
       if(seq==null||seq.length==0){
           return null;
       }
       List<LinkedList> list = new ArrayList<LinkedList>();
       int len = seq.length;
       for(int i=0;i<len;i++){
           num[i]=1;
           LinkedList<Integer> llist= new LinkedList<Integer>();
           llist.addFirst((seq[i]));
           list.add(llist);
           for(int j=0;j<i;j++){
               if(seq[i]>(Integer)list.get(j).getFirst()){
                   num[j]= num[j]+1;
                   list.get(j).addFirst(seq[i]);
               }
           }
       }
       int maxtemp =0;
       int k =-1;
       for(int i=0;i<num.length;i++){         
          if(num[i]>maxtemp){
              maxtemp = num[i];
              k = i;
          }
       }
       return list.get(k);
   }
}

方法2、利用通常動態規劃的思路spa

  設置輔助數組Len[i],表示對於序列以A[i]爲結尾的子序列的最長遞增子序列的長度,則序列的最長遞增子序列爲max{Len[i]}(0<i<n);排序

b[i]的狀態轉移方程爲:隊列

b[i] = 1當i ==1;get

 b[i] = max{b[k]+1}(0<i<n;1<=k<i)it

代碼實現class

/**
     * Seq爲序列
     * n爲序列長度
     * */
    public int maxLenAsSubSeq(int[] Seq,int n){
        int[] Len = new int[n];
        int max =0;
        Len[0] =1;
        for(int i=1;i<n;i++){
            Len[i] =1;
            for(int j=0;j<i;j++){
                //System.out.println(Seq[i]+" "+Seq[j]);
                if((Seq[i]>Seq[j])&&(Len[j]+1)>Len[i]){
                    Len[i] = Len[j]+1;
                }
            }
            if(max<Len[i]){
                max =Len[i];
            }         
        }
        return max;
                                                                                                                 
    }

    固然,最長遞增子序列的求法還有其餘:好比:利用最大公共子序列。此方法的具體實現,下午更新,敬請關注j_0061.gif

繼續方法三:

   最大公共子序列方法:

   由於須要求解A序列的最大遞增子序列,咱們能夠將序列A進行排序,排序後的序列A'單調遞增,根據最大公共子序列的性質,咱們把A和A’的最大公共子序列求出來,其實就是A的最大遞增子序列,由於A’遞增,又知足最大公共。

代碼實現:

  //排序
    public int[] sort(int[] num){
          int[] numtemp = num;
          int numlen = numtemp.length;
          for(int i=0;i<numlen;i++){
              for(int j=i;j<numlen;j++){
                  if(numtemp[i]>numtemp[j]){
                      int temp = numtemp[i];
                      numtemp[i] = numtemp[j];
                      numtemp[j] =temp;
                  }
              }
          }
          return numtemp;
    }
/**
     * 最長公共子序列
     * seq1:第一個序列
     * seq2:第二個序列
     * */
    public int LongComSubSeq(int[] seq1,int[] seq2){       
        if(seq1==null||seq1.length==0||seq2==null||seq2.length==0){
            return -1;
        }
        int len1 = seq1.length+1;
        int len2 = seq2.length+1;
        //存放公共子串的長度
        int[][] LCSLen = new int[len1][len2];
        //存放
        int[][] LCSDrec = new int[len1][len2];
        //接下來三個循環爲初始化
        for(int i=0;i<len1;i++){
            LCSLen[i][0] = 0;
        }
        for(int j=0;j<len2;j++){
            LCSLen[0][j] = 0;
        }
        for(int i=0;i<len1;i++){
            for(int j=0;j<len2;j++){
                LCSDrec[i][j] =0;
            }
        }
        for(int i=1;i<len1;i++){
            for(int j=1;j<len2;j++){
                if(seq1[i-1] == seq2[j-1]){
                    //System.out.println("序列值seq1:"+seq1[i-1]);
                    // System.out.println("序列值seq2:"+seq2[j-1]);
                    LCSLen[i][j] = LCSLen[i-1][j-1]+1;
                    // System.out.println("序列長度:"+LCSLen[i][j]);
                    LCSDrec[i][j] = 1;
                }else if(LCSLen[i-1][j]>LCSLen[i][j-1]){
                    LCSLen[i][j] = LCSLen[i-1][j];
                    LCSDrec[i][j] = 2;
                }else {
                    LCSLen[i][j] =LCSLen[i][j-1];
                    LCSDrec[i][j] = 3;
                }
                  
            }
        }
        LCSPrint(LCSDrec,seq1,len1-1,len2-1);
        return LCSLen[len1-1][len2-1];     
    }
    //最長公共子序列輸出函數
    public void LCSPrint(int[][] LCSDrec,int[] seq1,int len1,int len2){
        if(LCSDrec==null||seq1==null||len1<=0||len2<=0){
            return;
        }
        if(LCSDrec[len1][len2]==1){
            System.out.println(" "+seq1[len1-1]);          
            LCSPrint(LCSDrec,seq1,len1-1,len2-1);
        }else if(LCSDrec[len1][len2]==2){
            LCSPrint(LCSDrec,seq1,len1-1,len2);
        }else{
            LCSPrint(LCSDrec,seq1,len1,len2-1);
        }      
    }
相關文章
相關標籤/搜索