數組中最長遞增子序列問題研究(2)

來源:互聯網
上載者:User

在上一篇文章中,我們知道如何得到一個一維數組的最長遞增子序列的長度,但是我們並不知道這個子序列是什麼!如何去列舉出來一個滿足要求的這樣一個最長遞增子序列呢?

在之前講述的第二種方法中,我們藉助了一個minV數組,這個數組對於接下來的實現是有協助的。我們從一個數組的第一個元素開始遍曆,一直遍曆到這個元素對應的lis數組中的值不大於最長遞增子序列的長度。我們假設使用current指示想獲得的最終最長遞增子序列的第current個元素,如如果當前current等於1,則表示接下來想找子序列中的第一個元素。每找完一個就將current加1,尋找下一個元素。對於相同lis值的元素我們還需要做一些判斷。下面是具體實現的演算法:

public static int lis2(int[] array){if(array==null||array.length==0)return -1;int len=array.length;int[] lis=new int[len];int maxlength=1;int[] minV=new int[len+2];minV[0]=minArray(array)-1;minV[1]=array[0];Arrays.fill(lis, 1);for(int i=1;i<len;i++){int j;for(j=maxlength;j>=0;j--){if(array[i]>minV[j]){lis[i]=j+1;break;}}if(lis[i]>maxlength){maxlength=lis[i];minV[lis[i]]=array[i];}else if(minV[j]<array[i]&&array[i]<minV[j+1]){minV[j+1]=array[i];}}minV[maxlength+1]=Integer.MAX_VALUE;System.out.println(Arrays.toString(lis));int current=1;for(int i=0;i<lis.length&¤t<=maxlength;i++){if(lis[i]==current){if(array[i]>minV[current+1])continue;System.out.print(array[i]+" ");current++;}}System.out.println();return maxlength;}

運行結果如下:

1 2 4 5 7 長度為:5用時:285272納秒

如果有更好的方法還請大家指教啊。

上面給出了一種尋找一個最長遞迴子序列的方法,我們知道,對於一個數組來說,可能還有多個最長遞增子序列(這些最長遞增子序列的長度肯定相等),我們如何去獲得所有的最長遞增子序列並將它們全部都列舉出來呢?我想了個方法,跟大家分享一下,如果大家有好的方法可以共用一下!

我的思路是:使用遞迴的方法。我們編寫一個能夠從某個下標開始尋找子序列中第level個數的函數,例如outputLIS(int level,int index,int[] lis,int[] array,int[] minV),其中level表示我們要尋找的子序列中的第多少位元字,index表示從那個下標開始尋找,array是原數組,lis儲存的是相應元素在最後遞增子序列中的可能位置,minV[i]儲存的是長度為i的最長遞增子序列的最大元素的最小值。當然在該方法中我們還要藉助另外一個數組資訊,這個數組用來標誌原數組中的某個元素是否被選中在最長遞增子序列中。下面給出具體的演算法:

//輸出所有最長遞迴子序列private static void outputLIS(int level,int index,int[] lis,int[] array,int[] minV){if(level==maxlength+1){for(int i=0;i<flag.length;i++){if(flag[i]){System.out.print(array[i]+" ");}}System.out.println();return;}while(lis[index]!=level&&index<array.length)index++;while(index<array.length&&lis[index]<level+1){if(lis[index]==level&&array[index]<minV[lis[index]+1]){flag[index]=true;outputLIS(level+1,index+1,lis,array,minV);flag[index]=false;}index++;}}

運行結果如下:

1 2 4 5 7 -1 2 4 5 7 長度為:5用時:422708納秒

接下來我把完整的程式附上供大家參考。lis1隻求出最長遞增子序列的長度,lis2求出長度並列出一種最長遞增子序列,lis3求出長度並列舉出所有的最長遞增子序列。

package com.application.sample;import java.util.Arrays;import java.util.Iterator;import java.util.Stack;//求一個序列的最長遞增子序列public class LISsample {private static boolean[] flag;private static int maxlength;public static void main(String[] args) {// TODO Auto-generated method stubint[] arr={1,-1,2,-2,4,-3,5,-6,7};long start=System.nanoTime();System.out.println("長度為:"+lis1(arr));long end=System.nanoTime();System.out.println("用時:"+(end-start)+"納秒");start=System.nanoTime();System.out.println("長度為:"+lis2(arr));end=System.nanoTime();System.out.println("用時:"+(end-start)+"納秒");start=System.nanoTime();System.out.println("長度為:"+lis3(arr));end=System.nanoTime();System.out.println("用時:"+(end-start)+"納秒");}public static int lis1(int[] array){if(array==null||array.length==0)return -1;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[j]<array[i]&&(lis[j]+1)>lis[i]){lis[i]=lis[j]+1;}}}System.out.println(Arrays.toString(lis));return maxArray(lis);}public static int lis2(int[] array){if(array==null||array.length==0)return -1;int len=array.length;int[] lis=new int[len];int maxlength=1;int[] minV=new int[len+2];minV[0]=minArray(array)-1;minV[1]=array[0];Arrays.fill(lis, 1);for(int i=1;i<len;i++){int j;for(j=maxlength;j>=0;j--){if(array[i]>minV[j]){lis[i]=j+1;break;}}if(lis[i]>maxlength){maxlength=lis[i];minV[lis[i]]=array[i];}else if(minV[j]<array[i]&&array[i]<minV[j+1]){minV[j+1]=array[i];}}minV[maxlength+1]=Integer.MAX_VALUE;System.out.println(Arrays.toString(lis));int current=1;for(int i=0;i<lis.length&¤t<=maxlength;i++){if(lis[i]==current){if(array[i]>minV[current+1])continue;System.out.print(array[i]+" ");current++;}}System.out.println();return maxlength;}public static int lis3(int[] array){if(array==null||array.length==0)return -1;int len=array.length;flag=new boolean[len];int[] lis=new int[len];int maxlength=1;int[] minV=new int[len+2];minV[0]=Integer.MIN_VALUE;minV[1]=array[0];Arrays.fill(lis, 1);//for(int i=1;i<len;i++)//{//int j;//for(j=lis[i-1];j>0;j--)//{//if(array[i]>minV[j])//{//lis[i]=j+1;//break;//}//}//if(lis[i]>maxlength)//{//maxlength=lis[i];//minV[lis[i]]=array[i];//}else if(minV[j]<array[i]&&array[i]<minV[j+1])//{//minV[j+1]=array[i];//}//}for(int i=1;i<len;i++){int j;for(j=maxlength;j>=0;j--){if(array[i]>minV[j]){lis[i]=j+1;break;}}if(lis[i]>maxlength){maxlength=lis[i];minV[lis[i]]=array[i];}else if(minV[j]<array[i]&&array[i]<minV[j+1]){minV[j+1]=array[i];}}System.out.println(Arrays.toString(lis));minV[maxlength+1]=Integer.MAX_VALUE;System.out.println(Arrays.toString(minV));LISsample.maxlength=maxlength;outputLIS(1,0,lis,array,minV);return maxlength;}//輸出所有最長遞迴子序列private static void outputLIS(int level,int index,int[] lis,int[] array,int[] minV){if(level==maxlength+1){for(int i=0;i<flag.length;i++){if(flag[i]){System.out.print(array[i]+" ");}}System.out.println();return;}while(lis[index]!=level&&index<array.length)index++;while(index<array.length&&lis[index]<level+1){if(lis[index]==level&&array[index]<minV[lis[index]+1]){flag[index]=true;outputLIS(level+1,index+1,lis,array,minV);flag[index]=false;}index++;}}private static int minArray(int[] array){int result=array[0];for(int i=1;i<array.length;i++){if(array[i]<result)result=array[i];}return result;}private static int maxArray(int[] array){int result=array[0];for(int i=1;i<array.length;i++){if(array[i]>result)result=array[i];}return result;}}

整體的運行結果如下所示:

[1, 1, 2, 1, 3, 1, 4, 1, 5]長度為:5用時:360476納秒[1, 1, 2, 1, 3, 1, 4, 1, 5]1 2 4 5 7 長度為:5用時:433169納秒[1, 1, 2, 1, 3, 1, 4, 1, 5][-2147483648, -6, 2, 4, 5, 7, 2147483647, 0, 0, 0, 0]1 2 4 5 7 -1 2 4 5 7 長度為:5用時:451083納秒

大家有什麼意見和好的方法可以說說,謝謝!轉載請註明出處。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.