我们给了一个由数字组成的字符串,我们可以将这些数字分组为子组(但要保持其原始顺序)。任务是计算分组的数量,以使得对于除最后一个分组以外的每个子分组,子分组中的数字总和小于或等于其右侧紧邻的子分组中的数字总和。 。
例如,数字1119的有效数字分组为(1-11-9)。第一个子组的数字总和是1,下一个子组是2,最后一个子组是9。每个子组的总和小于或等于其直接右数。
例子 :
Input : "1119"
Output: 7
Sub-groups: [1-119], [1-1-19], [1-11-9], [1-1-1-9],
[11-19] and [111-9].
Note : Here we have included [1119] in the group and
the sum of digits is 12 and this group has no
immediate right.
Input : "1234"
Output: 6
Sub-groups : [1234], [1-234], [12-34], [1-2-3-4],
[12-3-4] and [1-2-34]
令“长度”为输入数字的长度。递归解决方案是考虑从0个length-1到每个位置。对于每个位置,递归计算其后的所有可能的子组。下面是朴素的递归解决方案的C++实现。
C++
// C++ program to count number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal to
// its immediate right subgroup.
#include
using namespace std;
// Function to find the subgroups
int countGroups(int position,
int previous_sum,
int length, char *num)
{
// Terminating Condition
if (position == length)
return 1;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
// Total number of subgroups
// till current position
return res;
}
// Driver Code
int main()
{
char num[] = "1119";
int len = strlen(num);
cout << countGroups(0, 0, len, num);
return 0;
}
Java
// Java program to count number
// of ways to group digits of
// a number such that sum of
// digits in every subgroup is
// less than or equal to its
// immediate right subgroup.
import java.io.*;
class GFG
{
// Function to find
// the subgroups
static int countGroups(int position,
int previous_sum,
int length,
String num)
{
// Terminating Condition
if (position == length)
return 1;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num.charAt(i) - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
// Total number of subgroups
// till current position
return res;
}
// Driver Code
public static void main (String[] args)
{
String num = "1119";
int len =num .length();
System.out.println(countGroups(0, 0,
len, num));
}
}
// This code is contributed by anuj_67.
Python3
# Python3 program to count
# number of ways to group digits
# of a number such that sum of
# digits in every subgroup
# is less than or equal to its immediate
# right subgroup.
# Function to find the subgroups
def countGroups(position, previous_sum,
length, num):
# Terminating Condition
if(position == length):
return 1
res = 0
# sum of digits
sum = 0
# Traverse all digits from
# current position to rest
# of the length of string
for i in range(position, length):
sum = sum + int(num[i])
# If forward_sum is greater
# than the previous sum,
# then call the method again
if (sum >= previous_sum):
# Note : We pass current
# sum as previous sum
res = res + countGroups(i + 1, sum, length, num)
# Total number of subgroups
# till the current position
return res
# Driver Code
if __name__=='__main__':
num = "1119"
len = len(num)
print(countGroups(0, 0, len, num))
# This code is contributed by
# Sanjit_Prasad
C#
// C# program to count number
// of ways to group digits of
// a number such that sum of
// digits in every subgroup is
// less than or equal to its
// immediate right subgroup.
using System;
class GFG
{
// Function to find
// the subgroups
static int countGroups(int position,
int previous_sum,
int length,
String num)
{
// Terminating Condition
if (position == length)
return 1;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
// Total number of subgroups
// till current position
return res;
}
// Driver Code
public static void Main ()
{
String num = "1119";
int len = num.Length;
Console.Write(countGroups(0, 0, len, num));
}
}
// This code is contributed by 29AjayKumar
PHP
= $previous_sum)
// Note : We pass current
// sum as previous sum
$res += countGroups($i + 1, $sum,
$length, $num);
}
// Total number of subgroups
// till current position
return $res;
}
// Driver Code
$num = "1119";
$len = strlen($num);
echo countGroups(0, 0, $len, $num);
// This code is contributed by ajit
?>
Javascript
C++
// C++ program to count number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
#include
using namespace std;
// Maximum length of
// input number string
const int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
int dp[MAX][9*MAX + 1];
// Function to find the count
// of splits with given condition
int countGroups(int position,
int previous_sum,
int length, char *num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
// countGroups for current
// sub-group is 0
dp[position][previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
int main()
{
char num[] = "1119";
int len = strlen(num);
// Initialize dp table
memset(dp, -1, sizeof(dp));
cout << countGroups(0, 0, len, num);
return 0;
}
Java
// Java program to count the number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
class GFG
{
// Maximum length of
// input number string
static int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
static int dp[][] = new int[MAX][9 * MAX + 1];
// Function to find the count
// of splits with given condition
static int countGroups(int position,
int previous_sum,
int length, char []num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
// countGroups for current
// sub-group is 0
dp[position][previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
public static void main(String[] args)
{
char num[] = "1119".toCharArray();
int len = num.length;
// Initialize dp table
for(int i = 0; i < dp.length; i++)
{
for(int j = 0;j < 9 * MAX + 1; j++){
dp[i][j] = -1;
}
}
System.out.println(countGroups(0, 0, len, num));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 program to count the number of
# ways to group digits of a number
# such that sum of digits in every
# subgroup is less than or equal
# to its immediate right subgroup.
# Maximum length of
# input number string
MAX = 40
# A memoization table to store
# results of subproblems length
# of string is 40 and maximum
# sum will be 9 * 40 = 360.
dp = [[ -1 for i in range(9 * MAX + 1)]
for i in range(MAX)]
# Function to find the count
# of splits with given condition
def countGroups(position, previous_sum,
length, num):
# Terminating Condition
if (position == length):
return 1
# If already evaluated for
# a given sub problem then
# return the value
if (dp[position][previous_sum] != -1):
return dp[position][previous_sum]
# countGroups for current
# sub-group is 0
dp[position][previous_sum] = 0
res = 0
# sum of digits
sum = 0
# Traverse all digits from
# current position to rest
# of the length of string
for i in range(position,length):
sum += (ord(num[i]) - ord('0'))
# If forward_sum is greater
# than the previous sum,
# then call the method again
if (sum >= previous_sum):
# Note : We pass current
# sum as previous sum
res += countGroups(i + 1, sum,
length, num)
dp[position][previous_sum] = res
# total number of subgroups
# till the current position
return res
# Driver Code
num = "1119"
len = len(num)
print(countGroups(0, 0, len, num))
# This code is contributed by Mohit Kumar
C#
// C# program to count number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
using System;
class GFG
{
// Maximum length of
// input number string
static int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
static int[,] dp = new int[MAX, 9 * MAX + 1];
// Function to find the count
// of splits with given condition
static int countGroups(int position,
int previous_sum,
int length, char[] num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position,previous_sum] != -1)
return dp[position,previous_sum];
// countGroups for current
// sub-group is 0
dp[position,previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position,previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
static void Main()
{
char[] num = {'1', '1', '1', '9'};
int len = num.Length;
// Initialize dp table
for(int i = 0; i < MAX; i++)
for(int j = 0; j < 9 * MAX + 1; j++)
dp[i, j] = -1;
Console.Write(countGroups(0, 0, len, num));
}
}
// This code is contributed by DrRoot_
输出 :
7
如果我们仔细研究以上递归解决方案,我们会注意到可能存在重叠的子问题。例如,如果输入数字为12345,则对于position = 3和previous_sum = 3,我们重复两次。同样,对于位置4和previous_sum = 7,我们重复两次。因此,可以使用动态编程来优化上述解决方案。下面是针对此问题的基于动态编程的解决方案。
- 最大数字总和可以是9 * length,其中“ length”是输入数字的长度。
- 创建一个2D数组int dp [MAX] [9 * MAX],其中MAX是输入数字的最大可能长度。值dp [position] [previous]将存储“ position”和“ previous_sum”的结果。
- 如果当前的子问题已经评估过,即; dp [position] [previous_sum]!= -1,然后使用此结果,否则递归计算其值。
- 如果在总和中包括当前位置数字,即; sum = sum + num [position]-‘0’,求和变得大于等于先前的总和,然后递增结果并为num中的下一个位置调用问题。
- 如果position == length,则我们已成功遍历当前子组,并且返回1;否则,返回0。
下面是上述算法的实现。
C++
// C++ program to count number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
#include
using namespace std;
// Maximum length of
// input number string
const int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
int dp[MAX][9*MAX + 1];
// Function to find the count
// of splits with given condition
int countGroups(int position,
int previous_sum,
int length, char *num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
// countGroups for current
// sub-group is 0
dp[position][previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
int main()
{
char num[] = "1119";
int len = strlen(num);
// Initialize dp table
memset(dp, -1, sizeof(dp));
cout << countGroups(0, 0, len, num);
return 0;
}
Java
// Java program to count the number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
class GFG
{
// Maximum length of
// input number string
static int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
static int dp[][] = new int[MAX][9 * MAX + 1];
// Function to find the count
// of splits with given condition
static int countGroups(int position,
int previous_sum,
int length, char []num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
// countGroups for current
// sub-group is 0
dp[position][previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
public static void main(String[] args)
{
char num[] = "1119".toCharArray();
int len = num.length;
// Initialize dp table
for(int i = 0; i < dp.length; i++)
{
for(int j = 0;j < 9 * MAX + 1; j++){
dp[i][j] = -1;
}
}
System.out.println(countGroups(0, 0, len, num));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 program to count the number of
# ways to group digits of a number
# such that sum of digits in every
# subgroup is less than or equal
# to its immediate right subgroup.
# Maximum length of
# input number string
MAX = 40
# A memoization table to store
# results of subproblems length
# of string is 40 and maximum
# sum will be 9 * 40 = 360.
dp = [[ -1 for i in range(9 * MAX + 1)]
for i in range(MAX)]
# Function to find the count
# of splits with given condition
def countGroups(position, previous_sum,
length, num):
# Terminating Condition
if (position == length):
return 1
# If already evaluated for
# a given sub problem then
# return the value
if (dp[position][previous_sum] != -1):
return dp[position][previous_sum]
# countGroups for current
# sub-group is 0
dp[position][previous_sum] = 0
res = 0
# sum of digits
sum = 0
# Traverse all digits from
# current position to rest
# of the length of string
for i in range(position,length):
sum += (ord(num[i]) - ord('0'))
# If forward_sum is greater
# than the previous sum,
# then call the method again
if (sum >= previous_sum):
# Note : We pass current
# sum as previous sum
res += countGroups(i + 1, sum,
length, num)
dp[position][previous_sum] = res
# total number of subgroups
# till the current position
return res
# Driver Code
num = "1119"
len = len(num)
print(countGroups(0, 0, len, num))
# This code is contributed by Mohit Kumar
C#
// C# program to count number of
// ways to group digits of a number
// such that sum of digits in every
// subgroup is less than or equal
// to its immediate right subgroup.
using System;
class GFG
{
// Maximum length of
// input number string
static int MAX = 40;
// A memoization table to store
// results of subproblems length
// of string is 40 and maximum
// sum will be 9 * 40 = 360.
static int[,] dp = new int[MAX, 9 * MAX + 1];
// Function to find the count
// of splits with given condition
static int countGroups(int position,
int previous_sum,
int length, char[] num)
{
// Terminating Condition
if (position == length)
return 1;
// If already evaluated for
// a given sub problem then
// return the value
if (dp[position,previous_sum] != -1)
return dp[position,previous_sum];
// countGroups for current
// sub-group is 0
dp[position,previous_sum] = 0;
int res = 0;
// sum of digits
int sum = 0;
// Traverse all digits from
// current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');
// If forward_sum is greater
// than the previous sum,
// then call the method again
if (sum >= previous_sum)
// Note : We pass current
// sum as previous sum
res += countGroups(i + 1, sum,
length, num);
}
dp[position,previous_sum] = res;
// total number of subgroups
// till current position
return res;
}
// Driver Code
static void Main()
{
char[] num = {'1', '1', '1', '9'};
int len = num.Length;
// Initialize dp table
for(int i = 0; i < MAX; i++)
for(int j = 0; j < 9 * MAX + 1; j++)
dp[i, j] = -1;
Console.Write(countGroups(0, 0, len, num));
}
}
// This code is contributed by DrRoot_
输出 :
7