📜  计算所有递增的子序列

📅  最后修改于: 2021-09-17 07:26:43             🧑  作者: Mango

我们得到一个数字数组(值在 0 到 9 的范围内)。任务是计算数组中所有可能的子序列,使得每个子序列中的每个数字都大于它在子序列中的前一个数字。

例子:

Input : arr[] = {1, 2, 3, 4}
Output: 15
There are total increasing subsequences
{1}, {2}, {3}, {4}, {1,2}, {1,3}, {1,4}, 
{2,3}, {2,4}, {3,4}, {1,2,3}, {1,2,4}, 
{1,3,4}, {2,3,4}, {1,2,3,4}

Input : arr[] = {4, 3, 6, 5}
Output: 8
Sub-sequences are {4}, {3}, {6}, {5}, 
{4,6}, {4,5}, {3,6}, {3,5}

Input : arr[] = {3, 2, 4, 5, 4}
Output : 14
Sub-sequences are {3}, {2}, {4}, {3,4},
{2,4}, {5}, {3,5}, {2,5}, {4,5}, {3,2,5}
{3,4,5}, {4}, {3,4}, {2,4}

方法一(类似于LIS)

一个简单的解决方案是使用最长递增子序列 (LIS) 问题的动态规划解决方案。像 LIS 问题一样,我们首先计算在每个索引处结束的递增子序列的计数。最后,我们返回所有值的总和(在 LCS 问题中,我们返回所有值的最大值)。

// We count all increasing subsequences ending at every 
// index i
subCount(i) = Count of increasing subsequences ending 
              at arr[i]. 

// Like LCS, this value can be recursively computed
subCount(i) = 1 + ∑ subCount(j) 
              where j is index of all elements
              such that arr[j] < arr[i] and j < i.
1 is added as every element itself is a subsequence
of size 1.

// Finally we add all counts to get the result.
Result = ∑ subCount(i)
         where i varies from 0 to n-1.

插图:

For example, arr[] = {3, 2, 4, 5, 4}

// There are no smaller elements on left of arr[0] 
// and arr[1]
subCount(0) = 1
subCount(1) = 1  

// Note that arr[0] and arr[1] are smaller than arr[2]
subCount(2) = 1 + subCount(0) + subCount(1)  = 3

subCount(3) = 1 + subCount(0) + subCount(1) + subCount(2) 
            = 1 + 1 + 1 + 3
            = 6
  
subCount(3) = 1 + subCount(0) + subCount(1)
            = 1 + 1 + 1
            = 3
                             
Result = subCount(0) + subCount(1) + subCount(2) + subCount(3)
       = 1 + 1 + 3 + 6 + 3
       = 14.

时间复杂度:O(n 2 )
辅助空间:O(n)
参考这个实现。

方法二(高效)

上面的解决方案没有使用给定数组中只有 10 个可能值的事实。我们可以通过使用数组 count[] 来使用这个事实,这样 count[d] 存储小于 d 的当前计数数字。

For example, arr[] = {3, 2, 4, 5, 4}

// We create a count array and initialize it as 0.
count[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

// Note that here value is used as index to store counts
count[3] += 1 = 1  // i = 0, arr[0] = 3
count[2] += 1 = 1  // i = 1, arr[0] = 2

// Let us compute count for arr[2] which is 4
count[4] += 1 + count[3] + count[2] += 1 + 1 + 1  = 3

// Let us compute count for arr[3] which is 5
count[5] += 1 + count[3] + count[2] + count[4] 
         += 1 + 1 + 1 + 3
         = 6

// Let us compute count for arr[4] which is 4
count[4] += 1 + count[0] + count[1]
         += 1 + 1 + 1
         += 3
         = 3 + 3
         = 6
            
Note that count[] = {0, 0, 1, 1, 6, 6, 0, 0, 0, 0}                  
Result = count[0] + count[1] + ... + count[9]
       = 1 + 1 + 6 + 6 {count[2] = 1, count[3] = 1
                        count[4] = 6, count[5] = 6} 
       = 14.

下面是上述想法的实现。

C++
// C++ program to count increasing subsequences
// in an array of digits.
#include
using namespace std;
 
// Function To Count all the sub-sequences
// possible in which digit is greater than
// all previous digits arr[] is array of n
// digits
int countSub(int arr[], int n)
{
    // count[] array is used to store all sub-
    // sequences possible using that digit
    // count[] array covers all the digit
    // from 0 to 9
    int count[10] = {0};
 
    // scan each digit in arr[]
    for (int i=0; i=0; j--)
            count[arr[i]] += count[j];
 
        // store sum of all sub-sequences plus
        // 1 in count[] array
        count[arr[i]]++;
    }
 
    // now sum up the all sequences possible in
    // count[] array
    int result = 0;
    for (int i=0; i<10; i++)
        result += count[i];
 
    return result;
}
 
// Driver program to run the test case
int main()
{
    int arr[] = {3, 2, 4, 5, 4};
    int n = sizeof(arr)/sizeof(arr[0]);
 
    cout << countSub(arr,n);
    return 0;
}


Java
// Java program to count increasing
// subsequences in an array of digits.
import java.io.*;
 
class GFG {
 
    // Function To Count all the sub-sequences
    // possible in which digit is greater than
    // all previous digits arr[] is array of n
    // digits
    static int countSub(int arr[], int n)
    {
        // count[] array is used to store all
        // sub-sequences possible using that
        // digit count[] array covers all
        // the digit from 0 to 9
        int count[] = new int[10]; 
 
        // scan each digit in arr[]
        for (int i = 0; i < n; i++)
        {
            // count all possible sub-
            // sequences by the digits
            // less than arr[i] digit
            for (int j = arr[i] - 1; j >= 0; j--)
                count[arr[i]] += count[j]; 
                 
            // store sum of all sub-sequences
            // plus 1 in count[] array
            count[arr[i]]++;
        }  
 
        // now sum up the all sequences
        // possible in count[] array
        int result = 0;
        for (int i = 0; i < 10; i++)
            result += count[i];
 
        return result;
    }
 
    // Driver program to run the test case
    public static void main(String[] args)
    {
        int arr[] = {3, 2, 4, 5, 4};
        int n = arr.length;
 
        System.out.println(countSub(arr,n));
    }
}
// This code is contributed by Prerna Saini


Python3
# Python3 program to count increasing
# subsequences in an array of digits.
 
# Function To Count all the sub-
# sequences possible in which digit
# is greater than all previous digits
# arr[] is array of n digits
def countSub(arr, n):
 
    # count[] array is used to store all
    # sub-sequences possible using that
    # digit count[] array covers all the
    # digit from 0 to 9
    count = [0 for i in range(10)]
 
    # scan each digit in arr[]
    for i in range(n):
     
        # count all possible sub-sequences by
        # the digits less than arr[i] digit
        for j in range(arr[i] - 1, -1, -1):
            count[arr[i]] += count[j]
 
        # store sum of all sub-sequences
        # plus 1 in count[] array
        count[arr[i]] += 1
     
 
    # Now sum up the all sequences
    # possible in count[] array
    result = 0
    for i in range(10):
        result += count[i]
 
    return result
 
# Driver Code
arr = [3, 2, 4, 5, 4]
n = len(arr)
print(countSub(arr, n))
 
# This code is contributed by Anant Agarwal.


C#
// C# program to count increasing
// subsequences in an array of digits.
using System;
class GFG {
 
    // Function To Count all the sub-sequences
    // possible in which digit is greater than
    // all previous digits arr[] is array of n
    // digits
    static int countSub(int []arr, int n)
    {
        // count[] array is used to store all
        // sub-sequences possible using that
        // digit count[] array covers all
        // the digit from 0 to 9
        int []count = new int[10]; 
 
        // scan each digit in arr[]
        for (int i = 0; i < n; i++)
        {
            // count all possible sub-
            // sequences by the digits
            // less than arr[i] digit
            for (int j = arr[i] - 1; j >= 0; j--)
                count[arr[i]] += count[j]; 
                 
            // store sum of all sub-sequences
            // plus 1 in count[] array
            count[arr[i]]++;
        }  
 
        // now sum up the all sequences
        // possible in count[] array
        int result = 0;
        for (int i = 0; i < 10; i++)
            result += count[i];
 
        return result;
    }
 
    // Driver program
    public static void Main()
    {
        int []arr = {3, 2, 4, 5, 4};
        int n = arr.Length;
 
        Console.WriteLine(countSub(arr,n));
    }
}
// This code is contributed by Anant Agarwal.


Javascript


输出:

14

时间复杂度:O(n) 请注意,内部循环最多运行 10 次。
辅助空间:O(1) 注意 count 最多有 10 个元素。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程