Count Number of Balanced Permutations
HardPrompt
You are given a string num. A string of digits is called balanced if the sum of the digits at even indices is equal to the sum of the digits at odd indices.
Return the number of distinct permutations of num that are balanced.
Since the answer may be very large, return it modulo 109 + 7.
A permutation is a rearrangement of all the characters of a string.
Example 1:
Input: num = "123"
Output: 2
Explanation:
- The distinct permutations of
numare"123","132","213","231","312"and"321". - Among them,
"132"and"231"are balanced. Thus, the answer is 2.
Example 2:
Input: num = "112"
Output: 1
Explanation:
- The distinct permutations of
numare"112","121", and"211". - Only
"121"is balanced. Thus, the answer is 1.
Example 3:
Input: num = "12345"
Output: 0
Explanation:
- None of the permutations of
numare balanced, so the answer is 0.
Constraints:
2 <= num.length <= 80numconsists of digits'0'to'9'only.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves generating every distinct permutation of the input string num. For each permutation generated, we then check if it satisfies the 'balanced' condition: the sum of digits at even indices equals the sum of digits at odd indices. We keep a count of all such balanced permutations.
Algorithm
- Create a frequency map (e.g., an array of size 10) to count the occurrences of each digit in the input string
num. - Implement a recursive backtracking function, say
generatePermutations(index, currentPermutation). - The base case for the recursion is when
indexreaches the length of the string,N. At this point, thecurrentPermutationis complete. - In the base case, check if the generated permutation is balanced. To do this, iterate through the permutation, summing digits at even and odd indices separately. If
sum_even == sum_odd, increment a global counter for balanced permutations. - In the recursive step, iterate through all possible digits (0-9). If the count of a digit in the frequency map is greater than 0, it's available for placement.
- Place the available digit at the current
indexof the permutation. Decrement its count in the frequency map. - Make a recursive call for the next index:
generatePermutations(index + 1, ...). - After the recursive call returns, backtrack by restoring the count of the digit in the frequency map. This allows the digit to be used in different positions in other permutations.
- The initial call to the function would be
generatePermutations(0, new char[N]). - The final value of the counter is the answer. Note that this approach does not handle the modulo operation as it's computationally infeasible to reach large numbers that would require it.
Walkthrough
The most straightforward way to solve this problem is to generate all possible unique arrangements of the digits in num and test each one for the balanced property.
We can use a recursive backtracking algorithm to explore all permutations. To handle duplicate digits in num and ensure that we only generate distinct permutations, we first count the frequency of each digit. The recursive function then builds a permutation character by character. At each step, it tries to place an available digit (one whose count is greater than zero) and then recurses. After the recursive call, it backtracks by undoing the choice.
Once a full permutation is formed (i.e., the recursion reaches its base case), we check if it's balanced by summing the digits at even and odd positions and comparing the sums. If they are equal, we increment our answer.
import java.util.Arrays; class Solution { long count = 0; int n; public int countBalancedPermutations(String num) { this.n = num.length(); int[] freq = new int[10]; for (char c : num.toCharArray()) { freq[c - '0']++; } generate(0, new char[n], freq); return (int) count; } private void generate(int index, char[] p, int[] freq) { if (index == n) { if (isBalanced(p)) { count++; } return; } for (int i = 0; i <= 9; i++) { if (freq[i] > 0) { p[index] = (char) (i + '0'); freq[i]--; generate(index + 1, p, freq); freq[i]++; // backtrack } } } private boolean isBalanced(char[] p) { int evenSum = 0; int oddSum = 0; for (int i = 0; i < p.length; i++) { if (i % 2 == 0) { evenSum += p[i] - '0'; } else { oddSum += p[i] - '0'; } } return evenSum == oddSum; }}This approach is far too slow for the given constraints due to the factorial growth in the number of permutations.
Complexity
Time
O((N! / Π(count_i!)) * N). The number of distinct permutations is given by the multinomial coefficient, and for each permutation, we perform an O(N) check. This is prohibitively expensive for N up to 80.
Space
O(N) for the recursion depth and to store the current permutation being built.
Trade-offs
Pros
Conceptually simple and easy to understand.
Correct for very small input sizes.
Cons
Extremely inefficient and will time out for all but the smallest inputs.
The number of permutations can be massive (up to 80!), making this approach computationally infeasible.
It's not practical for the given constraints (
num.length <= 80).
Solutions
Solution
class Solution {private final int[] cnt = new int[10];private final int mod = (int)1 e9 + 7;private Integer[][][][] f;private long[][] c;public int countBalancedPermutations(String num) { int s = 0; for (char c : num.toCharArray()) { cnt[c - '0']++; s += c - '0'; } if (s % 2 == 1) { return 0; } int n = num.length(); int m = n / 2 + 1; f = new Integer[10][s / 2 + 1][m][m + 1]; c = new long[m + 1][m + 1]; c[0][0] = 1; for (int i = 1; i <= m; i++) { c[i][0] = 1; for (int j = 1; j <= i; j++) { c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } return dfs(0, s / 2, n / 2, (n + 1) / 2); }private int dfs(int i, int j, int a, int b) { if (i > 9) { return ((j | a | b) == 0) ? 1 : 0; } if (a == 0 && j != 0) { return 0; } if (f[i][j][a][b] != null) { return f[i][j][a][b]; } int ans = 0; for (int l = 0; l <= Math.min(cnt[i], a); ++l) { int r = cnt[i] - l; if (r >= 0 && r <= b && l * i <= j) { int t = (int)(c[a][l] * c[b][r] % mod * dfs(i + 1, j - l * i, a - l, b - r) % mod); ans = (ans + t) % mod; } } return f[i][j][a][b] = ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.