给定一个大小为N的数组 arr[]和一个整数K ,任务是通过将数组拆分为 K个子集,使每个子集仅由唯一的数组元素组成,从而最小化每个子集的最大和最小元素之间的差值之和。
例子:
Input: arr[] = { 6, 3, 8, 1, 3, 1, 2, 2 }, K = 4
Output: 6
Explanation:
One of the optimal ways to split the array into K(= 4) subsets are { { 1, 2 }, { 2, 3 }, { 6, 8 }, { 1, 4 } }.
Sum of difference of maximum and minimum element present in each subset = { (2 – 1) + (3 – 2) + (8 – 6) + (3 – 1) } = 6.
Therefore, the required output is 6
Input: arr[] = { 2, 2, 1, 1 }, K = 1
Output: -1
方法:该问题可以使用带有位掩码的动态规划来解决。以下是递推关系:
mask: ith bit of mask checks if array element is already selected in a subset or not.
l: index of last element selected in a subset.
j: index of current element selected in a subset.
If count of set bits in mask mod (N / K) == 1:
dp[mask][l] = min(dp[mask][l], dp[mask ^ (1 << l)][j])
Otherwise,
dp[mask][j] = min(dp[mask][j], dp[mask ^ (1 << j)][l] + nums[l] – nums[j])
请按照以下步骤解决问题:
- 迭代 mask 的所有可能值,即[0, 2 N – 1]
- 初始化一个数组,比如n_z_bits[] ,以存储子集中已经选择的元素的数量。
- 使用上面的递推关系并填充递推关系的所有可能的dp状态。
- 最后,打印dp[(1 << N ) – 1] 中的最小元素。
下面是上述方法的实现:
Python3
# Python program to implement
# the above approach
from itertools import permutations
from itertools import combinations
# Function to minimize the sum of
# difference between maximums and
# minimums of K subsets of an array
def MinimizeSum(nums, k):
# Stores count of elements
# in an array
n = len(nums)
# Base Case
if k == n:
return 0
# Initialize DP[][] array
dp = [[float("inf")] * n for _ in range(1 << n)]
# Sort the array
nums.sort()
# Mark i-th element
# as not selected
for i in range(n):
dp[1 << i][i] = 0
# Iterate over all possible
# values of mask
for mask in range(1 << n):
# Store count of set bits
# in mask
n_z_bits = []
# Store index of element which is
# already selected in a subset
for p, c in enumerate(bin(mask)):
if c == "1":
temp = len(bin(mask)) - p - 1
n_z_bits.append(temp)
# If count of set bits in mask
# mod (n // k) equal to 1
if len(n_z_bits) % (n//k) == 1:
for j, l in permutations(n_z_bits, 2):
temp = dp[mask ^ (1 << l)][j]
dp[mask][l] = min(dp[mask][l], temp)
else:
for j, l in combinations(n_z_bits, 2):
if nums[j] != nums[l]:
# Check if l-th element
# is already selected or not
mask_t = mask ^ (1 << l)
temp = (dp[mask_t][j] +
nums[j] - nums[l])
# Update dp[mask][l]
dp[mask][l] = min(dp[mask][l],
temp)
# Return minimum element
# from dp[(1 << N) - 1]
if min(dp[-1]) != float("inf"):
return min(dp[-1])
# If dp[-1] is inf then the
# partition is not possible
else:
return -1
# Driver Code
if __name__ == "__main__":
# Given array
arr = [ 6, 3, 8, 1, 3, 1, 2, 2 ]
K = 4
# Function call
print(MinimizeSum(arr, K))
6
时间复杂度: O(N* 2 N )
辅助空间: O(N * 2 N )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。