📜  最长递增子序列(LIS)的构建和打印LIS序列

📅  最后修改于: 2021-04-29 02:11:42             🧑  作者: Mango

Java代码:

The Longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence
of a given sequence such that all elements of the subsequence are sorted in increasing order.
For example, the length of LIS for {10, 22, 9, 33, 21, 50, 41, 60, 80} is 6 and LIS is {10, 22, 33, 50, 60, 80}.
Java
package BIT;
 
import java.util.ArrayList;
import java.util.Iterator;
 
public class LongestIncreasingSubsequence {
    public static void main(String[] args) {
//        int array[] = {10, 22, 9, 33, 21, 50, 41, 60, 80};
//        int array[] = {10, 2, 9, 3, 5, 4, 6, 8};
        int array[] = {10, 9, 8, 6, 5, 4};
        ArrayList list = new ArrayList();
        ArrayList longestList = new ArrayList();
        int currentMax;
        int highestCount = 0;
        for(int i = 0; i < array.length;i++)
        {
            currentMax = Integer.MIN_VALUE;
            for(int j = i;j < array.length; j++)
            {
                if(array[j] > currentMax)
                {
                    list.add(array[j]);
                    currentMax = array[j];
                }
            }
             
            //Compare previous highest subsequence
            if(highestCount < list.size())
            {
                highestCount = list.size();
                longestList = new ArrayList(list); 
            }  
            list.clear();
        }
        System.out.println();
         
        //Print list
        Iterator itr = longestList.iterator();
        System.out.println("The Longest subsequence");
        while(itr.hasNext())
        {
            System.out.print(itr.next() + " ");
        }
        System.out.println();
        System.out.println("Length of LIS: " + highestCount);
    }
     
}


C#
using System;
using System.Collections.Generic;
 
class longestIncreasingSubsequence
{
    public static void Main(String[] args)
    {
        int []array = {10, 22, 9, 33, 21, 50, 41, 60, 80};
        // int []array = {10, 2, 9, 3, 5, 4, 6, 8};
        //int []array = {10, 9, 8, 6, 5, 4};
        List list = new List();
        List longestList = new List();
        int currentMax;
        int highestCount = 0;
        for(int i = 0; i < array.Length;i++)
        {
            currentMax = int.MinValue;
            for(int j = i;j < array.Length; j++)
            {
                if(array[j] > currentMax)
                {
                    list.Add(array[j]);
                    currentMax = array[j];
                }
            }
             
            // Compare previous highest subsequence
            if(highestCount < list.Count)
            {
                highestCount = list.Count;
                longestList = new List(list);
            }
            list.Clear();
        }
        Console.WriteLine();
         
        // Print list
        Console.WriteLine("The longest subsequence");
        foreach(int itr in longestList)
        {
            Console.Write(itr + " ");
        }
        Console.WriteLine();
        Console.WriteLine("Length of LIS: " + highestCount);
    }
}
 
// This code is contributed by 29AjayKumar


C++
/* Dynamic Programming solution to construct Longest
   Increasing Subsequence */
#include 
#include 
using namespace std;
 
// Utility function to print LIS
void printLIS(vector& arr)
{
    for (int x : arr)
        cout << x << " ";
    cout << endl;
}
 
// Function to construct and print Longest Increasing
// Subsequence
void constructPrintLIS(int arr[], int n)
{
    // L[i] - The longest increasing sub-sequence
    // ends with arr[i]
    vector > L(n);
 
    // L[0] is equal to arr[0]
    L[0].push_back(arr[0]);
 
    // start from index 1
    for (int i = 1; i < n; i++)
    {
        // do for every j less than i
        for (int j = 0; j < i; j++)
        {
            /* L[i] = {Max(L[j])} + arr[i]
            where j < i and arr[j] < arr[i] */
            if ((arr[i] > arr[j]) &&
                    (L[i].size() < L[j].size() + 1))
                L[i] = L[j];
        }
 
        // L[i] ends with arr[i]
        L[i].push_back(arr[i]);
    }
 
    // L[i] now stores increasing sub-sequence of
    // arr[0..i] that ends with arr[i]
    vector max = L[0];
 
    // LIS will be max of all increasing sub-
    // sequences of arr
    for (vector x : L)
        if (x.size() > max.size())
            max = x;
 
    // max will contain LIS
    printLIS(max);
}
 
// Driver function
int main()
{
    int arr[] = { 3, 2, 6, 4, 5, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // construct and print LIS of arr
    constructPrintLIS(arr, n);
 
    return 0;
}


Java
// Java program for
// the above approach
 
// Dynamic Programming
// solution to conLongest
// Increasing Subsequence
import java.util.*;
class GFG{
 
// Utility function to print LIS
static void printLIS(Vector arr)
{
  for (int x : arr)
    System.out.print(x + " ");
  System.out.println();
}
 
// Function to conand print
// Longest Increasing Subsequence
static void constructPrintLIS(int arr[],
                              int n)
{
  // L[i] - The longest increasing
  // sub-sequence ends with arr[i]
  Vector L[] = new Vector[n];
  for (int i = 0; i < L.length; i++)
    L[i] = new Vector();
   
  // L[0] is equal to arr[0]
  L[0].add(arr[0]);
 
  // Start from index 1
  for (int i = 1; i < n; i++)
  {
    // Do for every j less than i
    for (int j = 0; j < i; j++)
    {
      //L[i] = {Max(L[j])} + arr[i]
      // where j < i and arr[j] < arr[i]
      if ((arr[i] > arr[j]) &&
          (L[i].size() < L[j].size() + 1))
        L[i] = L[j];
    }
 
    // L[i] ends with arr[i]
    L[i].add(arr[i]);
  }
 
  // L[i] now stores increasing sub-sequence of
  // arr[0..i] that ends with arr[i]
  Vector max = L[0];
   
  // LIS will be max of all increasing sub-
  // sequences of arr
  for (Vector x : L)
    if (x.size() > max.size())
      max = x;
 
  // max will contain LIS
  printLIS(max);
}
 
// Driver function
public static void main(String[] args)
{
  int arr[] = {3, 2, 4, 5, 1};
  int n = arr.length;
 
  // print LIS of arr
  constructPrintLIS(arr, n);
}
}
 
// This code is contributed by gauravrajput1


Python3
# Dynamic Programming solution to construct Longest
# Increasing Subsequence
 
# Utility function to print LIS
def printLIS(arr: list):
    for x in arr:
        print(x, end=" ")
    print()
 
# Function to construct and print Longest Increasing
# Subsequence
def constructPrintLIS(arr: list, n: int):
 
    # L[i] - The longest increasing sub-sequence
    # ends with arr[i]
    l = [[] for i in range(n)]
 
    # L[0] is equal to arr[0]
    l[0].append(arr[0])
 
    # start from index 1
    for i in range(1, n):
 
        # do for every j less than i
        for j in range(i):
 
            # L[i] = {Max(L[j])} + arr[i]
            # where j < i and arr[j] < arr[i]
            if arr[i] > arr[j] and (len(l[i]) < len(l[j]) + 1):
                l[i] = l[j].copy()
 
        # L[i] ends with arr[i]
        l[i].append(arr[i])
 
    # L[i] now stores increasing sub-sequence of
    # arr[0..i] that ends with arr[i]
    maxx = l[0]
 
    # LIS will be max of all increasing sub-
    # sequences of arr
    for x in l:
        if len(x) > len(maxx):
            maxx = x
 
    # max will contain LIS
    printLIS(maxx)
 
# Driver Code
if __name__ == "__main__":
 
    arr = [3, 2, 6, 4, 5, 1]
    n = len(arr)
 
    # construct and print LIS of arr
    constructPrintLIS(arr, n)
 
# This code is contributed by
# sanjeev2552


C#
// Dynamic Programming solution to construct Longest
// Increasing Subsequence
using System;
using System.Collections.Generic;
class GFG
{
     
    // Utility function to print LIS
    static void printLIS(List arr)
    {
        foreach(int x in arr)
        {
            Console.Write(x + " ");
        }
        Console.WriteLine();
    }
      
    // Function to construct and print Longest Increasing
    // Subsequence
    static void constructPrintLIS(int[] arr, int n)
    {
       
        // L[i] - The longest increasing sub-sequence
        // ends with arr[i]
        List> L = new List>();
        for(int i = 0; i < n; i++)
        {
            L.Add(new List());
        }
      
        // L[0] is equal to arr[0]
        L[0].Add(arr[0]);
      
        // start from index 1
        for (int i = 1; i < n; i++)
        {
            // do for every j less than i
            for (int j = 0; j < i; j++)
            {
                /* L[i] = {Max(L[j])} + arr[i]
                where j < i and arr[j] < arr[i] */
                if ((arr[i] > arr[j]) && (L[i].Count < L[j].Count + 1))
                    L[i] = L[j];
            }
      
            // L[i] ends with arr[i]
            L[i].Add(arr[i]);
        }
      
        // L[i] now stores increasing sub-sequence of
        // arr[0..i] that ends with arr[i]
        List max = L[0];
      
        // LIS will be max of all increasing sub-
        // sequences of arr
        foreach(List x in L)
        {
            if (x.Count > max.Count)
            {
                max = x;
            }
        }
      
        // max will contain LIS
        printLIS(max);
    }
 
  // Driver code
  static void Main()
  {
    int[] arr = { 3, 2, 4, 5, 1 };
    int n = arr.Length;
  
    // construct and print LIS of arr
    constructPrintLIS(arr, n);
  }
}
 
// This code is contributed by divyesh072019


最长的递增子序列(LIS)问题是找到给定序列的最长的子序列的长度,以使该子序列的所有元素都按递增的顺序排序。
例子:

Input:  [10, 22, 9, 33, 21, 50, 41, 60, 80]
Output: [10, 22, 33, 50, 60, 80] 
OR [10 22 33 41 60 80] or any other LIS of same length.

在上一篇文章中,我们讨论了最长增长子序列问题。但是,该帖子仅涵盖了与LIS查询大小有关的代码,而没有涵盖LIS的构造。在本文中,我们将讨论如何使用前面讨论过的类似DP解决方案打印LIS。
令arr [0..n-1]为输入数组。我们定义向量L,使得L [i]本身就是一个存储以arr [i]结尾的arr LIS的向量。例如,对于数组[3,2,6,6,4,5,1],

L[0]: 3
L[1]: 2
L[2]: 2 6
L[3]: 2 4
L[4]: 2 4 5
L[5]: 1

因此,对于索引i,L [i]可以递归写为–

L[0] = {arr[O]}
L[i] = {Max(L[j])} + arr[i] 
where j < i and arr[j] < arr[i] and if there is no such j then L[i] = arr[i]

以下是上述想法的实现–

C++

/* Dynamic Programming solution to construct Longest
   Increasing Subsequence */
#include 
#include 
using namespace std;
 
// Utility function to print LIS
void printLIS(vector& arr)
{
    for (int x : arr)
        cout << x << " ";
    cout << endl;
}
 
// Function to construct and print Longest Increasing
// Subsequence
void constructPrintLIS(int arr[], int n)
{
    // L[i] - The longest increasing sub-sequence
    // ends with arr[i]
    vector > L(n);
 
    // L[0] is equal to arr[0]
    L[0].push_back(arr[0]);
 
    // start from index 1
    for (int i = 1; i < n; i++)
    {
        // do for every j less than i
        for (int j = 0; j < i; j++)
        {
            /* L[i] = {Max(L[j])} + arr[i]
            where j < i and arr[j] < arr[i] */
            if ((arr[i] > arr[j]) &&
                    (L[i].size() < L[j].size() + 1))
                L[i] = L[j];
        }
 
        // L[i] ends with arr[i]
        L[i].push_back(arr[i]);
    }
 
    // L[i] now stores increasing sub-sequence of
    // arr[0..i] that ends with arr[i]
    vector max = L[0];
 
    // LIS will be max of all increasing sub-
    // sequences of arr
    for (vector x : L)
        if (x.size() > max.size())
            max = x;
 
    // max will contain LIS
    printLIS(max);
}
 
// Driver function
int main()
{
    int arr[] = { 3, 2, 6, 4, 5, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // construct and print LIS of arr
    constructPrintLIS(arr, n);
 
    return 0;
}

Java

// Java program for
// the above approach
 
// Dynamic Programming
// solution to conLongest
// Increasing Subsequence
import java.util.*;
class GFG{
 
// Utility function to print LIS
static void printLIS(Vector arr)
{
  for (int x : arr)
    System.out.print(x + " ");
  System.out.println();
}
 
// Function to conand print
// Longest Increasing Subsequence
static void constructPrintLIS(int arr[],
                              int n)
{
  // L[i] - The longest increasing
  // sub-sequence ends with arr[i]
  Vector L[] = new Vector[n];
  for (int i = 0; i < L.length; i++)
    L[i] = new Vector();
   
  // L[0] is equal to arr[0]
  L[0].add(arr[0]);
 
  // Start from index 1
  for (int i = 1; i < n; i++)
  {
    // Do for every j less than i
    for (int j = 0; j < i; j++)
    {
      //L[i] = {Max(L[j])} + arr[i]
      // where j < i and arr[j] < arr[i]
      if ((arr[i] > arr[j]) &&
          (L[i].size() < L[j].size() + 1))
        L[i] = L[j];
    }
 
    // L[i] ends with arr[i]
    L[i].add(arr[i]);
  }
 
  // L[i] now stores increasing sub-sequence of
  // arr[0..i] that ends with arr[i]
  Vector max = L[0];
   
  // LIS will be max of all increasing sub-
  // sequences of arr
  for (Vector x : L)
    if (x.size() > max.size())
      max = x;
 
  // max will contain LIS
  printLIS(max);
}
 
// Driver function
public static void main(String[] args)
{
  int arr[] = {3, 2, 4, 5, 1};
  int n = arr.length;
 
  // print LIS of arr
  constructPrintLIS(arr, n);
}
}
 
// This code is contributed by gauravrajput1

Python3

# Dynamic Programming solution to construct Longest
# Increasing Subsequence
 
# Utility function to print LIS
def printLIS(arr: list):
    for x in arr:
        print(x, end=" ")
    print()
 
# Function to construct and print Longest Increasing
# Subsequence
def constructPrintLIS(arr: list, n: int):
 
    # L[i] - The longest increasing sub-sequence
    # ends with arr[i]
    l = [[] for i in range(n)]
 
    # L[0] is equal to arr[0]
    l[0].append(arr[0])
 
    # start from index 1
    for i in range(1, n):
 
        # do for every j less than i
        for j in range(i):
 
            # L[i] = {Max(L[j])} + arr[i]
            # where j < i and arr[j] < arr[i]
            if arr[i] > arr[j] and (len(l[i]) < len(l[j]) + 1):
                l[i] = l[j].copy()
 
        # L[i] ends with arr[i]
        l[i].append(arr[i])
 
    # L[i] now stores increasing sub-sequence of
    # arr[0..i] that ends with arr[i]
    maxx = l[0]
 
    # LIS will be max of all increasing sub-
    # sequences of arr
    for x in l:
        if len(x) > len(maxx):
            maxx = x
 
    # max will contain LIS
    printLIS(maxx)
 
# Driver Code
if __name__ == "__main__":
 
    arr = [3, 2, 6, 4, 5, 1]
    n = len(arr)
 
    # construct and print LIS of arr
    constructPrintLIS(arr, n)
 
# This code is contributed by
# sanjeev2552

C#

// Dynamic Programming solution to construct Longest
// Increasing Subsequence
using System;
using System.Collections.Generic;
class GFG
{
     
    // Utility function to print LIS
    static void printLIS(List arr)
    {
        foreach(int x in arr)
        {
            Console.Write(x + " ");
        }
        Console.WriteLine();
    }
      
    // Function to construct and print Longest Increasing
    // Subsequence
    static void constructPrintLIS(int[] arr, int n)
    {
       
        // L[i] - The longest increasing sub-sequence
        // ends with arr[i]
        List> L = new List>();
        for(int i = 0; i < n; i++)
        {
            L.Add(new List());
        }
      
        // L[0] is equal to arr[0]
        L[0].Add(arr[0]);
      
        // start from index 1
        for (int i = 1; i < n; i++)
        {
            // do for every j less than i
            for (int j = 0; j < i; j++)
            {
                /* L[i] = {Max(L[j])} + arr[i]
                where j < i and arr[j] < arr[i] */
                if ((arr[i] > arr[j]) && (L[i].Count < L[j].Count + 1))
                    L[i] = L[j];
            }
      
            // L[i] ends with arr[i]
            L[i].Add(arr[i]);
        }
      
        // L[i] now stores increasing sub-sequence of
        // arr[0..i] that ends with arr[i]
        List max = L[0];
      
        // LIS will be max of all increasing sub-
        // sequences of arr
        foreach(List x in L)
        {
            if (x.Count > max.Count)
            {
                max = x;
            }
        }
      
        // max will contain LIS
        printLIS(max);
    }
 
  // Driver code
  static void Main()
  {
    int[] arr = { 3, 2, 4, 5, 1 };
    int n = arr.Length;
  
    // construct and print LIS of arr
    constructPrintLIS(arr, n);
  }
}
 
// This code is contributed by divyesh072019

输出:

2 4 5