📜  最长子序列递增的Java程序

📅  最后修改于: 2021-04-25 00:40:46             🧑  作者: Mango

最长增长子序列(LIS)问题是找到给定序列的最长子序列的长度,以使子序列的所有元素都按升序排序。例如,{10、22、9、33、21、50、41、60、80}的LIS长度为6,LIS为{10、22、33、50、60、80}。
最长增长子序列

更多示例:

Input  : arr[] = {3, 10, 2, 1, 20}
Output : Length of LIS = 3
The longest increasing subsequence is 3, 10, 20

Input  : arr[] = {3, 2}
Output : Length of LIS = 1
The longest increasing subsequences are {3} and {2}

Input : arr[] = {50, 3, 10, 7, 40, 80}
Output : Length of LIS = 4
The longest increasing subsequence is {3, 7, 40, 80}

最佳子结构:
令arr [0..n-1]为输入数组,令L(i)为以索引i结尾的LIS的长度,以使arr [i]为LIS的最后一个元素。
然后,L(i)可以递归写为:
L(i)= 1 + max(L(j))其中0 如果不存在这样的j,则L(i)= 1。
为了找到给定数组的LIS,我们需要返回max(L(i)),其中0 因此,我们看到LIS问题满足最佳子结构属性,因为可以使用子问题的解决方案来解决主要问题。

以下是LIS问题的简单递归实现。它遵循上面讨论的递归结构。

/* A Naive Java Program for LIS Implementation */
class LIS {
    static int max_ref; // stores the LIS
  
    /* To make use of recursive calls, this function must return
   two things:
   1) Length of LIS ending with element arr[n-1]. We use
      max_ending_here for this purpose
   2) Overall maximum as the LIS may end with an element
      before arr[n-1] max_ref is used this purpose.
   The value of LIS of full array of size n is stored in
   *max_ref which is our final result */
    static int _lis(int arr[], int n)
    {
        // base case
        if (n == 1)
            return 1;
  
        // 'max_ending_here' is length of LIS ending with arr[n-1]
        int res, max_ending_here = 1;
  
        /* Recursively get all LIS ending with arr[0], arr[1] ...
           arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
           max ending with arr[n-1] needs to be updated, then
           update it */
        for (int i = 1; i < n; i++) {
            res = _lis(arr, i);
            if (arr[i - 1] < arr[n - 1] && res + 1 > max_ending_here)
                max_ending_here = res + 1;
        }
  
        // Compare max_ending_here with the overall max. And
        // update the overall max if needed
        if (max_ref < max_ending_here)
            max_ref = max_ending_here;
  
        // Return length of LIS ending with arr[n-1]
        return max_ending_here;
    }
  
    // The wrapper function for _lis()
    static int lis(int arr[], int n)
    {
        // The max variable holds the result
        max_ref = 1;
  
        // The function _lis() stores its result in max
        _lis(arr, n);
  
        // returns max
        return max_ref;
    }
  
    // driver program to test above functions
    public static void main(String args[])
    {
        int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
        int n = arr.length;
        System.out.println("Length of lis is "
                           + lis(arr, n) + "\n");
    }
}
/*This code is contributed by Rajat Mishra*/
输出:
Length of lis is 5

重叠子问题:
考虑到上述实现,下面是大小为4的数组的递归树。lis(n)给出了arr []的LIS长度。

lis(4)
        /        |     
      lis(3)    lis(2)   lis(1)
     /           /
   lis(2) lis(1) lis(1)
   /
lis(1)

我们可以看到,有许多子问题一次又一次地得到解决。因此,此问题具有“重叠子结构”属性,可以通过使用“记忆化”或“制表”来避免相同子问题的重新计算。以下是LIS问题的列表化实施。

/* Dynamic Programming Java implementation of LIS problem */
  
class LIS {
    /* lis() returns the length of the longest increasing
       subsequence in arr[] of size n */
    static int lis(int arr[], int n)
    {
        int lis[] = new int[n];
        int i, j, max = 0;
  
        /* Initialize LIS values for all indexes */
        for (i = 0; i < n; i++)
            lis[i] = 1;
  
        /* Compute optimized LIS values in bottom up manner */
        for (i = 1; i < n; i++)
            for (j = 0; j < i; j++)
                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
                    lis[i] = lis[j] + 1;
  
        /* Pick maximum of all LIS values */
        for (i = 0; i < n; i++)
            if (max < lis[i])
                max = lis[i];
  
        return max;
    }
  
    public static void main(String args[])
    {
        int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
        int n = arr.length;
        System.out.println("Length of lis is " + lis(arr, n) + "\n");
    }
}
/*This code is contributed by Rajat Mishra*/
输出:
Length of lis is 5

请参考有关动态编程的完整文章。设置3(最长递增子序列)以获取更多详细信息!