计算将二进制数组划分为每个包含 K 个 0 的子数组的方法
给定一个大小为N的二进制数组arr[]和一个整数K ,任务是计算将数组划分为非重叠子数组的方法数,其中每个子数组正好有K个数字 0。
例子:
Input: arr[] = [ 0, 0, 1, 1, 0, 1, 0], K = 2
Output: 3
Explanation: Different possible partitions are:
{{0, 0}, {1, 1, 0, 1, 0}}, {{0, 0, 1}, {1, 0, 1, 0}}, {{0, 0, 1, 1}, {0, 1, 0}}. So, the output will be 3.
Input: arr[] = {0, 0, 1, 0, 1, 0}, K = 2
Output: 2
Input: arr[] = [1, 0, 1, 1], K = 2
Output: 0
方法:解决问题的方法基于以下思想:
If jth 0 is the last 0 for a subarray and (j+1)th 0 is the first 0 of another subarray, then the possible number of ways to partition into those two subarrays is one more than the number of 1s in between jth and (j+1)th 0.
从上面的观察,可以说划分子数组的全部可能方式是K*x th和(K*x + 1)th 0 之间 1 的计数的乘积,对于所有可能的 x 使得 K* x 不超过数组中 0 的总数。
请按照下图更好地理解问题,
插图:
Consider array arr[] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0}, K = 2
Index of 2nd 0 and 3rd 0 are 1 and 4
=> Total number of 1s in between = 2.
=> Possible partition with these 0s = 2 + 1 = 3.
=> Total possible partitions till now = 3
Index of 4th 0 and 5th 0 are 6 and 8
=> Total number of 1s in between = 1.
=> Possible partition with these 0s = 1 + 1 = 2.
=> Total possible partitions till now = 3*2 = 6
The possible partitions are 6:
{{0, 0}, {1, 1, 0, 1, 0}, {1, 0, 0}}, {{0, 0}, {1, 1, 0, 1, 0, 1}, {0, 0}},
{{0, 0, 1}, {1, 0, 1, 0}, {1, 0, 0}}, {{0, 0, 1}, {1, 0, 1, 0, 1}, {0, 0}},
{{0, 0, 1, 1}, {0, 1, 0}, {1, 0, 0}}, {{0, 0, 1, 1}, {0, 1, 0, 1}, {0, 0}}
请按照以下步骤解决问题:
- 将计数器变量初始化为1 (声称至少存在一种这样的可能方式)。
- 如果少于K个 0 或者 0 的个数不能被K整除,那么这种划分是不可能的。
- 然后,对于每个可能的第 (K*x) 个和第(K*x + 1) 个0,使用上述观察计算可能的分区数,并将其与计数器变量相乘以获得可能的分区总数。
- 返回计数器变量的值。
这是上述方法的代码:
C++
// C++ program for above approach
#include
using namespace std;
// Function used to calculate the number of
// ways to divide the array
int number_of_ways(vector& arr, int K)
{
// Initialize a counter variable no_0 to
// calculate the number of 0
int no_0 = 0;
// Initialize a vector to
// store the indices of 0s
vector zeros;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] == 0) {
no_0++;
zeros.push_back(i);
}
}
// If number of 0 is not divisible by K
// or no 0 in the sequence return 0
if (no_0 % K || no_0 == 0)
return 0;
int res = 1;
// For every (K*n)th and (K*n+1)th 0
// calculate the distance between them
for (int i = K; i < zeros.size();) {
res *= (zeros[i] - zeros[i - 1]);
i += K;
}
// Return the number of such partitions
return res;
}
// Driver code
int main()
{
vector arr = { 0, 0, 1, 1, 0, 1, 0 };
int K = 2;
// Function call
cout << number_of_ways(arr, K) << endl;
return 0;
}
Python3
# Python3 program for above approach
# Function used to calculate the number of
# ways to divide the array
def number_of_ways(arr, K):
# Initialize a counter variable no_0 to
# calculate the number of 0
no_0 = 0
# Initialize am array to
# store the indices of 0s
zeros = []
for i in range(len(arr)):
if arr[i] == 0:
no_0 += 1
zeros.append(i)
# If number of 0 is not divisible by K
# or no 0 in the sequence return 0
if no_0 % K or no_0 == 0:
return 0
res = 1
# For every (K*n)th and (K*n+1)th 0
# calculate the distance between them
i = K
while (i < len(zeros)):
res *= (zeros[i] - zeros[i - 1])
i += K
# Return the number of such partitions
return res
# Driver code
arr = [0, 0, 1, 1, 0, 1, 0]
K = 2
# Function call
print(number_of_ways(arr, K))
# This code is contributed by phasing17.
Javascript
3
时间复杂度: O(N)
辅助空间: O(N)