最长单调子序列LIS的简单动态规划算法

    给定一个序列,要求求出该序列的最长单调子序列, 即 longest increasing subsequence

    这是一个经典的动态规划求解问题。

 

    设给定序列为 a[],大小为 n,如何求其最长单调子序列呢?

    考虑将最长单调子序列的长度作为所求的最优值

    最长单调子序列必定以序列a[]中的某一个元素结尾,这是废话。

    设序列count[i]为以a[i]结尾的最长单调子序列的长度,那么a[]的LIS的长度就是

             max{count[i]}, 对所有i

    显然此问题具有最优子结构性质,

    count[0] = 1, count[i] = max{count[j] | 0 <= j < i, a[j] < a[i]} + 1

   据此可得出简单的动态规划算法:

 

import java.util.Random;

 

/** sequence resolved with dynamic design

 * @author Ewan

 * @author http://blog.csdm.net/whmii

 */

public class Sequence { 

    /** the data of the sequence,

     * express as an array

     */

    private int[] a;

 

    /**default constructor

     * produce an array randomly

     */

    public Sequence() {

       long seed = System.nanoTime();

       Random rand = new Random(seed);

       int size = 5 + rand.nextInt(8);

       a = new int[size];

       for(int i = 0; i < size; i++) {

           a[i] = rand.nextInt(50);

       }

    }

 

    public String toString() {

       String result = "";

        for(int i = 0, len = a.length; i < len; i++) {

        result += a[i];

        result += "/t";

        }

        return result;

    }

 

    /** get out the LIS use dynamic design

     * time O(n*n)

     */

    public int[] LIS() {          

    int n = a.length;

    int currentLISLength; //LIS length end with current element

    int maxLength = 0;    //the result's length

        int endIndex = 0;        //the last element's index

        int[] count = new int[a.length]; //count[i] stores the LIS ends with a[i]

        int[] result;

        count[0] = 1;          //LIS contains one element at least

 

        for(int i = 1; i < n; i++) {

        currentLISLength = 0;

            for(int j = 0; j < i; j++) {

              if(a[j] <= a[i] && currentLISLength < count[j]) {

                 //a[j] is in LIS ends with a[i]

                  currentLISLength = count[j];

                }

            }

            count[i] = currentLISLength + 1; //compute a[i] self

 

            //compute the max length and last element's index of LIS

            if(count[i] > maxLength) {

                maxLength = count[i];

                endIndex = i;

        }

        }

 

        //store LIS into result[]

        result = new int[maxLength];

        int index = maxLength;

        result[--index] = a[endIndex];

        for(int i = endIndex, currentIndex = endIndex; i >=0; i--) {

        if(a[i] <= a[currentIndex] && count[i] == count[currentIndex] - 1) {

             result[--index] = a[i];

             currentIndex = i;

        }

        }

        return result;

    }

 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值