我们得到一个数字数组(值在 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 现场工作专业课程和学生竞争性编程现场课程。