Impresión de la suma máxima de la subsecuencia creciente

El problema de la subsecuencia creciente de suma máxima es encontrar la subsecuencia de suma máxima de una secuencia dada de modo que todos los elementos de la subsecuencia se ordenen en orden creciente.

Ejemplos: 

Input:  [1, 101, 2, 3, 100, 4, 5]
Output: [1, 2, 3, 100]

Input:  [3, 4, 5, 10]
Output: [3, 4, 5, 10]

Input:  [10, 5, 4, 3]
Output: [10]

Input:  [3, 2, 6, 4, 5, 1]
Output: [3, 4, 5]

En una publicación anterior , hemos discutido el problema de la subsecuencia creciente de suma máxima. Sin embargo, la publicación solo cubría el código relacionado con la búsqueda de la suma máxima de subsecuencias crecientes, pero no con la construcción de subsecuencias. En esta publicación, discutiremos cómo construir la Subsecuencia Creciente de Suma Máxima en sí misma.

Sea arr[0..n-1] la array de entrada. Definimos el vector L tal que L[i] es en sí mismo un vector que almacena la Subsecuencia Creciente de Suma Máxima de arr[0..i] que termina en arr[i]. Por lo tanto, para el índice i, L[i] puede escribirse recursivamente como 

L[0] = {arr[0]}
L[i] = {MaxSum(L[j])} + arr[i] where j < i and arr[j] < arr[i]
     = arr[i], if there is no j such that arr[j] < arr[i]

Por ejemplo, para la array [3, 2, 6, 4, 5, 1], 

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

A continuación se muestra la implementación de la idea anterior: 

C++

/* Dynamic Programming solution to construct
   Maximum Sum Increasing Subsequence */
#include <iostream>
#include <vector>
using namespace std;
 
// Utility function to calculate sum of all
// vector elements
int findSum(vector<int> arr)
{
    int sum = 0;
    for (int i : arr)
        sum += i;
    return sum;
}
 
// Function to construct Maximum Sum Increasing
// Subsequence
void printMaxSumIS(int arr[], int n)
{
    // L[i] - The Maximum Sum Increasing
    // Subsequence that ends with arr[i]
    vector<vector<int> > 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++) {
        // for every j less than i
        for (int j = 0; j < i; j++) {
            /* L[i] = {MaxSum(L[j])} + arr[i]
            where j < i and arr[j] < arr[i] */
            if ((arr[i] > arr[j])
                && (findSum(L[i]) < findSum(L[j])))
                L[i] = L[j];
        }
 
        // L[i] ends with arr[i]
        L[i].push_back(arr[i]);
 
        // L[i] now stores Maximum Sum Increasing
        // Subsequence of arr[0..i] that ends with
        // arr[i]
    }
 
    vector<int> res = L[0];
 
    // find max
    for (vector<int> x : L)
        if (findSum(x) > findSum(res))
            res = x;
 
    // max will contain result
    for (int i : res)
        cout << i << " ";
    cout << endl;
}
 
// Driver Code
int main()
{
    int arr[] = { 3, 2, 6, 4, 5, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // construct and print Max Sum IS of arr
    printMaxSumIS(arr, n);
 
    return 0;
}

Java

/* Dynamic Programming solution to construct
Maximum Sum Increasing Subsequence */
import java.util.*;
 
class GFG {
 
    // Utility function to calculate sum of all
    // vector elements
    static int findSum(Vector<Integer> arr)
    {
        int sum = 0;
        for (int i : arr)
            sum += i;
        return sum;
    }
 
    // Function to construct Maximum Sum Increasing
    // Subsequence
    static void printMaxSumIs(int[] arr, int n)
    {
 
        // L[i] - The Maximum Sum Increasing
        // Subsequence that ends with arr[i]
        @SuppressWarnings("unchecked")
        Vector<Integer>[] L = new Vector[n];
 
        for (int i = 0; i < n; 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++) {
 
            // for every j less than i
            for (int j = 0; j < i; j++) {
 
                /*
                * L[i] = {MaxSum(L[j])} + arr[i]
                  where j < i and arr[j] < arr[i]
                */
                if ((arr[i] > arr[j])
                    && (findSum(L[i]) < findSum(L[j]))) {
                    for (int k : L[j])
                        if (!L[i].contains(k))
                            L[i].add(k);
                }
            }
 
            // L[i] ends with arr[i]
            L[i].add(arr[i]);
 
            // L[i] now stores Maximum Sum Increasing
            // Subsequence of arr[0..i] that ends with
            // arr[i]
        }
 
        Vector<Integer> res = new Vector<>(L[0]);
        // res = L[0];
 
        // find max
        for (Vector<Integer> x : L)
            if (findSum(x) > findSum(res))
                res = x;
 
        // max will contain result
        for (int i : res)
            System.out.print(i + " ");
        System.out.println();
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] arr = { 3, 2, 6, 4, 5, 1 };
        int n = arr.length;
 
        // construct and print Max Sum IS of arr
        printMaxSumIs(arr, n);
    }
}
 
// This code is contributed by
// sanjeev2552

Python3

# Dynamic Programming solution to construct
# Maximum Sum Increasing Subsequence */
 
# Utility function to calculate sum of all
# vector elements
 
 
def findSum(arr):
 
    summ = 0
    for i in arr:
        summ += i
    return summ
 
# Function to construct Maximum Sum Increasing
# Subsequence
 
 
def printMaxSumIS(arr, n):
 
    # L[i] - The Maximum Sum Increasing
    # Subsequence that 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):
 
        # for every j less than i
        for j in range(i):
 
            # L[i] = {MaxSum(L[j])} + arr[i]
            # where j < i and arr[j] < arr[i]
            if ((arr[i] > arr[j]) and
                    (findSum(L[i]) < findSum(L[j]))):
                for e in L[j]:
                    if e not in L[i]:
                        L[i].append(e)
 
        # L[i] ends with arr[i]
        L[i].append(arr[i])
 
        # L[i] now stores Maximum Sum Increasing
        # Subsequence of arr[0..i] that ends with
        # arr[i]
 
    res = L[0]
 
    # find max
    for x in L:
        if (findSum(x) > findSum(res)):
            res = x
 
    # max will contain result
    for i in res:
        print(i, end=" ")
 
 
# Driver Code
arr = [3, 2, 6, 4, 5, 1]
n = len(arr)
 
# construct and prMax Sum IS of arr
printMaxSumIS(arr, n)
 
# This code is contributed by Mohit Kumar

C#

/* Dynamic Programming solution to construct
Maximum Sum Increasing Subsequence */
using System;
using System.Collections.Generic;
 
class GFG {
 
    // Utility function to calculate sum of all
    // vector elements
    static int findSum(List<int> arr)
    {
        int sum = 0;
        foreach(int i in arr) sum += i;
        return sum;
    }
 
    // Function to construct Maximum Sum Increasing
    // Subsequence
    static void printMaxSumIs(int[] arr, int n)
    {
 
        // L[i] - The Maximum Sum Increasing
        // Subsequence that ends with arr[i]
        List<int>[] L = new List<int>[ n ];
 
        for (int i = 0; i < n; i++)
            L[i] = new List<int>();
 
        // L[0] is equal to arr[0]
        L[0].Add(arr[0]);
 
        // start from index 1
        for (int i = 1; i < n; i++) {
 
            // for every j less than i
            for (int j = 0; j < i; j++) {
 
                /*
                * L[i] = {MaxSum(L[j])} + arr[i]
                where j < i and arr[j] < arr[i]
                */
                if ((arr[i] > arr[j])
                    && (findSum(L[i]) < findSum(L[j]))) {
                    foreach(int k in
                                L[j]) if (!L[i].Contains(k))
                        L[i]
                            .Add(k);
                }
            }
 
            // L[i] ends with arr[i]
            L[i].Add(arr[i]);
 
            // L[i] now stores Maximum Sum Increasing
            // Subsequence of arr[0..i] that ends with
            // arr[i]
        }
 
        List<int> res = new List<int>(L[0]);
        // res = L[0];
 
        // find max
        foreach(List<int> x in L) if (findSum(x)
                                      > findSum(res)) res
            = x;
 
        // max will contain result
        foreach(int i in res) Console.Write(i + " ");
        Console.WriteLine();
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int[] arr = { 3, 2, 6, 4, 5, 1 };
        int n = arr.Length;
 
        // construct and print Max Sum IS of arr
        printMaxSumIs(arr, n);
    }
}
 
// This code is contributed by PrinciRaj1992

Javascript

<script>
 
/* Dynamic Programming solution to construct
Maximum Sum Increasing Subsequence */
     
    // Utility function to calculate sum of all
    // vector elements
    function findSum(arr)
    {
        let sum = 0;
        for (let i=0;i<arr.length;i++)
            sum += arr[i];
        return sum;
    }
     
    // Function to construct Maximum Sum Increasing
    // Subsequence
    function printMaxSumIs(arr,n)
    {
        // L[i] - The Maximum Sum Increasing
        // Subsequence that ends with arr[i]
         
        let L = new Array(n);
  
        for (let i = 0; i < n; i++)
            L[i] = [];
  
        // L[0] is equal to arr[0]
        L[0].push(arr[0]);
  
        // start from index 1
        for (let i = 1; i < n; i++) {
  
            // for every j less than i
            for (let j = 0; j < i; j++) {
  
                /*
                * L[i] = {MaxSum(L[j])} + arr[i]
                  where j < i and arr[j] < arr[i]
                */
                if ((arr[i] > arr[j])
                    && (findSum(L[i]) < findSum(L[j])))
                    {
                    for (let k=0;k<L[j].length;k++)
                        if (!L[i].includes(L[j][k]))
                            L[i].push(L[j][k]);
                }
            }
  
            // L[i] ends with arr[i]
            L[i].push(arr[i]);
  
            // L[i] now stores Maximum Sum Increasing
            // Subsequence of arr[0..i] that ends with
            // arr[i]
        }
          
        let res = L[0];
        // res = L[0];
      
        // find max
        for (let x=0;x<L.length;x++)
            if (findSum(L[x]) > findSum(res))
                res = L[x];
  
        // max will contain result
        for (let i=0;i<res.length;i++)
            document.write(res[i] + " ");
        document.write("<br>");
    }
     
     // Driver Code
    let arr=[3, 2, 6, 4, 5, 1];
    let n = arr.length;
     
    // construct and print Max Sum IS of arr
    printMaxSumIs(arr, n);
     
 
// This code is contributed by unknown2108
 
</script>
Producción

3 4 5

 Podemos optimizar la solución de DP anterior eliminando la función findSum(). En cambio, podemos mantener otro vector/array para almacenar la suma de la subsecuencia creciente de suma máxima que termina con arr[i]. La implementación se puede ver aquí .

La complejidad temporal de la solución de programación dinámica anterior es O(n 2 ). 
El espacio auxiliar utilizado por el programa es O(n 2 ).

Enfoque 2: ( Uso de la programación dinámica Uso del espacio O(N)

El enfoque anterior cubría cómo construir una Subsecuencia Creciente de Suma Máxima en el tiempo O(N 2 ) y el espacio O(N 2 ). En este enfoque, optimizaremos la complejidad del espacio y construiremos la subsecuencia creciente de suma máxima en el tiempo O(N 2 ) y el espacio O(N).

  • Sea arr[0..n-1] la array de entrada.
  • Definimos un vector de pares L tal que L[i] primero almacena la Subsecuencia Creciente de Suma Máxima de arr[0..i] que termina en arr[i] y L[i].segundo almacena el índice del elemento anterior utilizado para generar la suma.
  • Como el primer elemento no tiene ningún elemento anterior, su índice sería -1 en L[0].

Por ejemplo, 

array = [3, 2, 6, 4, 5, 1]

L[0]: {3, -1}
L[1]: {2,  1}
L[2]: {9,  0}
L[3]: {7, 0}
L[4]: {12, 3}
L[5]: {1, 5}

Como podemos ver arriba, el valor de la Subsecuencia Creciente de Suma Máxima es 12. Para construir la Subsecuencia real usaremos el índice almacenado en L[i].segundo. Los pasos para construir la Subsecuencia se muestran a continuación: 

  • En un resultado vectorial, almacene el valor del elemento donde se encontró la Subsecuencia creciente de suma máxima (es decir, en currIndex = 4). Entonces, en el vector de resultados, agregaremos arr[currIndex].
  • Actualice currIndex a L[currIndex].segundo y repita el paso 1 hasta que currIndex no sea -1 o no cambie (es decir, currIndex == índice anterior).
  • Muestre los elementos del vector de resultado en orden inverso.

A continuación se muestra la implementación de la idea anterior: 

C++14

/* Dynamic Programming solution to construct
Maximum Sum Increasing Subsequence */
#include <bits/stdc++.h>
using namespace std;
 
// Function to construct and print the Maximum Sum
// Increasing Subsequence
void constructMaxSumIS(vector<int> arr, int n)
{
    // L[i] stores the value of Maximum Sum Increasing
    // Subsequence that ends with arr[i] and the index of
    // previous element used to construct the Subsequence
    vector<pair<int, int> > L(n);
 
    int index = 0;
    for (int i : arr) {
        L[index] = { i, index };
        index++;
    }
 
    // Set L[0].second equal to -1
    L[0].second = -1;
 
    // start from index 1
    for (int i = 1; i < n; i++) {
        // for every j less than i
        for (int j = 0; j < i; j++) {
            if (arr[i] > arr[j]
                and L[i].first < arr[i] + L[j].first) {
                L[i].first = arr[i] + L[j].first;
                L[i].second = j;
            }
        }
    }
 
    int maxi = INT_MIN, currIndex, track = 0;
 
    for (auto p : L) {
        if (p.first > maxi) {
            maxi = p.first;
            currIndex = track;
        }
        track++;
    }
 
    // Stores the final Subsequence
    vector<int> result;
 
    // Index of previous element
    // used to construct the Subsequence
    int prevoiusIndex;
 
    while (currIndex >= 0) {
        result.push_back(arr[currIndex]);
        prevoiusIndex = L[currIndex].second;
 
        if (currIndex == prevoiusIndex)
            break;
 
        currIndex = prevoiusIndex;
    }
 
    for (int i = result.size() - 1; i >= 0; i--)
        cout << result[i] << " ";
}
 
// Driver Code
int main()
{
    vector<int> arr = { 1, 101, 2, 3, 100, 4, 5 };
    int n = arr.size();
 
    // Function call
    constructMaxSumIS(arr, n);
 
    return 0;
}

Java

// Dynamic Programming solution to construct
// Maximum Sum Increasing Subsequence
import java.util.*;
import java.awt.Point;
 
class GFG{
     
// Function to construct and print the Maximum Sum
// Increasing Subsequence
static void constructMaxSumIS(List<Integer> arr, int n)
{
     
    // L.get(i) stores the value of Maximum Sum Increasing
    // Subsequence that ends with arr.get(i) and the index of
    // previous element used to construct the Subsequence
    List<Point> L = new ArrayList<Point>();
 
    int index = 0;
    for(int i : arr)
    {
        L.add(new Point(i, index));
        index++;
    }
 
    // Set L[0].second equal to -1
    L.set(0, new Point(L.get(0).x, -1));
 
    // Start from index 1
    for(int i = 1; i < n; i++)
    {
         
        // For every j less than i
        for(int j = 0; j < i; j++)
        {
            if (arr.get(i) > arr.get(j) &&
                L.get(i).x < arr.get(i) +
                L.get(j).x)
            {
                L.set(i, new Point(arr.get(i) +
                                     L.get(j).x, j));
            }
        }
    }
 
    int maxi = -100000000, currIndex = 0, track = 0;
 
    for(Point p : L)
    {
        if (p.x > maxi)
        {
            maxi = p.x;
            currIndex = track;
        }
        track++;
    }
 
    // Stores the final Subsequence
    List<Integer> result = new ArrayList<Integer>();
 
    // Index of previous element
    // used to construct the Subsequence
    int prevoiusIndex;
 
    while (currIndex >= 0)
    {
        result.add(arr.get(currIndex));
        prevoiusIndex = L.get(currIndex).y;
 
        if (currIndex == prevoiusIndex)
            break;
 
        currIndex = prevoiusIndex;
    }
 
    for(int i = result.size() - 1; i >= 0; i--)
        System.out.print(result.get(i) + " ");
}
 
// Driver Code
public static void main(String []s)
{
    List<Integer> arr = new ArrayList<Integer>();
    arr.add(1);
    arr.add(101);
    arr.add(2);
    arr.add(3);
    arr.add(100);
    arr.add(4);
    arr.add(5);
     
    int n = arr.size();
 
    // Function call
    constructMaxSumIS(arr, n);
}
}
 
// This code is contributed by rutvik_56

Python3

# Dynamic Programming solution to construct
# Maximum Sum Increasing Subsequence
import sys
 
# Function to construct and print the Maximum Sum
# Increasing Subsequence
def constructMaxSumIS(arr, n) :
 
    # L[i] stores the value of Maximum Sum Increasing
    # Subsequence that ends with arr[i] and the index of
    # previous element used to construct the Subsequence
    L = []
 
    index = 0
    for i in arr :
        L.append([i, index])
        index += 1
 
    # Set L[0].second equal to -1
    L[0][1] = -1
 
    # start from index 1
    for i in range(1, n) :
       
        # for every j less than i
        for j in range(i) :
            if (arr[i] > arr[j] and L[i][0] < arr[i] + L[j][0]) :
                L[i][0] = arr[i] + L[j][0]
                L[i][1] = j
 
    maxi, currIndex, track = -sys.maxsize, 0, 0
 
    for p in L :
        if (p[0] > maxi) :
            maxi = p[0]
            currIndex = track
     
        track += 1
 
    # Stores the final Subsequence
    result = []
 
    while (currIndex >= 0) :
        result.append(arr[currIndex])
        prevoiusIndex = L[currIndex][1]
 
        if (currIndex == prevoiusIndex) :
            break
 
        currIndex = prevoiusIndex
 
    for i in range(len(result) - 1, -1, -1) :
        print(result[i] , end = " ")
 
 
arr = [ 1, 101, 2, 3, 100, 4, 5 ]
n = len(arr)
 
# Function call
constructMaxSumIS(arr, n)
 
# This code is contributed by divyeshrabadiya07

C#

/* Dynamic Programming solution to construct
Maximum Sum Increasing Subsequence */
using System;
using System.Collections.Generic;
class GFG
{
     
    // Function to construct and print the Maximum Sum
    // Increasing Subsequence
    static void constructMaxSumIS(List<int> arr, int n)
    {
       
        // L[i] stores the value of Maximum Sum Increasing
        // Subsequence that ends with arr[i] and the index of
        // previous element used to construct the Subsequence
        List<Tuple<int, int>> L = new List<Tuple<int, int>>();
      
        int index = 0;
        foreach(int i in arr) {
            L.Add(new Tuple<int, int>(i, index));
            index++;
        }
      
        // Set L[0].second equal to -1
        L[0] = new Tuple<int, int>(L[0].Item1, -1);
      
        // start from index 1
        for (int i = 1; i < n; i++)
        {
           
            // for every j less than i
            for (int j = 0; j < i; j++)
            {
                if (arr[i] > arr[j] &&
                    L[i].Item1 < arr[i] +
                    L[j].Item1)
                {
                    L[i] = new Tuple<int,
                  int>(arr[i] + L[j].Item1, j);
                }
            }
        }
      
        int maxi = Int32.MinValue,
      currIndex = 0, track = 0;
      
        foreach(Tuple<int, int> p in L)
        {
            if (p.Item1 > maxi)
            {
                maxi = p.Item1;
                currIndex = track;
            }
            track++;
        }
      
        // Stores the final Subsequence
        List<int> result = new List<int>();
      
        // Index of previous element
        // used to construct the Subsequence
        int prevoiusIndex;
      
        while (currIndex >= 0)
        {
            result.Add(arr[currIndex]);
            prevoiusIndex = L[currIndex].Item2;
      
            if (currIndex == prevoiusIndex)
                break;
      
            currIndex = prevoiusIndex;
        }
      
        for (int i = result.Count - 1; i >= 0; i--)
            Console.Write(result[i] + " ");
    } 
 
  static void Main()
  {
    List<int> arr = new List<int>(new
                                  int[] { 1, 101, 2, 3, 100, 4, 5 });
    int n = arr.Count;
  
    // Function call
    constructMaxSumIS(arr, n);
  }
}
 
// This code is contributed by divyesh072019

Javascript

<script>
 
// Dynamic Programming solution to construct
// Maximum Sum Increasing Subsequence
 
// Function to construct and print the Maximum Sum
// Increasing Subsequence
function constructMaxSumIS(arr, n){
 
    // L[i] stores the value of Maximum Sum Increasing
    // Subsequence that ends with arr[i] and the index of
    // previous element used to construct the Subsequence
    let L = []
 
    let index = 0
    for(let i of arr){
        L.push([i, index])
        index += 1
    }
 
    // Set L[0].second equal to -1
    L[0][1] = -1
 
    // start from index 1
    for(let i=1;i<n;i++){
       
        // for every j less than i
        for(let j=0;j<i;j++){
            if (arr[i] > arr[j] && L[i][0] < arr[i] + L[j][0]){
                L[i][0] = arr[i] + L[j][0]
                L[i][1] = j
            }
        }
    }
 
    let maxi = Number.MIN_VALUE, currIndex = 0, track = 0
 
    for(let p of L){
        if (p[0] > maxi){
            maxi = p[0]
            currIndex = track
        }
     
        track += 1
    }
 
    // Stores the final Subsequence
    let result = []
 
    while (currIndex >= 0){
        result.push(arr[currIndex])
        let prevoiusIndex = L[currIndex][1]
 
        if (currIndex == prevoiusIndex)
            break
 
        currIndex = prevoiusIndex
    }
 
    for(let i=result.length - 1;i>=0;i--)
        document.write(result[i] ," ")
}
 
 
let arr = [ 1, 101, 2, 3, 100, 4, 5 ]
let n = arr.length
 
// Function call
constructMaxSumIS(arr, n)
 
// This code is contributed by shinjanpatra
 
</script>
Producción

1 2 3 100

Complejidad de tiempo: O(N 2 )
Complejidad de espacio: O(N)

Este artículo es una contribución de Aditya Goel . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *