给定一个由N 个整数组成的数组 arr[] ,任务是找到通过将数组划分为任意两个非空子集而获得的两个子集之和的最大差值。
注意:子集不能有任何公共元素。子集可以包含重复元素。
例子:
Input: arr[] = {1, 3, 2, 4, 5}
Output: 13
Explanation: The partitions {3, 2, 4, 5} and {1} maximizes the difference between the subsets.
Input: arr[] = {1, -5, 3, 2, -7}
Output: 18
Explanation: The partitions {1, 3, 2} and {-5, -7} maximizes the difference between the subsets.
方法:这个问题可以使用贪心方法来解决。在这个问题中,子集 A 和 B 都必须是非空的。所以我们必须在它们两个中至少放入一个元素。我们尽量使子集 A 中元素的总和尽可能大,而子集 B 中元素的总和尽可能小。最后我们打印 sum(A) – sum(B)。
请按照以下步骤解决问题:
- 当arr[ ] 同时包含非负数和负数时,将所有非负数放在子集 A 中,将负数放在子集 B 中,并打印sum(A) – sum(B) 。
- 当所有数字都是正数时,将所有数字放入子集 A 中,除了最小的正数放入子集 B 中,并打印sum(A) – sum(B) 。
- 当所有数均为负数时,将除最大负数外的所有数放入子集A中,并打印sum(A) – sum(B)。
下面是上述方法的实现:
C++
// C++ Program for the above approach
#include
using namespace std;
int maxSumAfterPartition(int arr[], int n)
{
// Stores the positive elements
vector pos;
// Stores the negative elements
vector neg;
// Stores the count of 0s
int zero = 0;
// Sum of all positive numbers
int pos_sum = 0;
// Sum of all negative numbers
int neg_sum = 0;
// Iterate over the array
for (int i = 0; i < n; i++) {
if (arr[i] > 0) {
pos.push_back(arr[i]);
pos_sum += arr[i];
}
else if (arr[i] < 0) {
neg.push_back(arr[i]);
neg_sum += arr[i];
}
else {
zero++;
}
}
// Stores the difference
int ans = 0;
// Sort the positive numbers
// in ascending order
sort(pos.begin(), pos.end());
// Sort the negative numbers
// in decreasing order
sort(neg.begin(), neg.end(), greater());
// Case 1: Include both positive
// and negative numbers
if (pos.size() > 0 && neg.size() > 0) {
ans = (pos_sum - neg_sum);
}
else if (pos.size() > 0) {
if (zero > 0) {
// Case 2: When all numbers are
// positive and array contains 0s
//Put all numbers in subset A and
//one 0 in subset B
ans = (pos_sum);
}
else {
// Case 3: When all numbers are positive
//Put all numbers in subset A except the
//smallest positive number which is put in B
ans = (pos_sum - 2 * pos[0]);
}
}
else {
if (zero > 0) {
// Case 4: When all numbers are
// negative and array contains 0s
// Put all numbers in subset B
// and one 0 in subset A
ans = (-1 * neg_sum);
}
else {
// Case 5: When all numbers are negative
// Place the largest negative number
// in subset A and remaining in B
ans = (neg[0] - (neg_sum - neg[0]));
}
}
return ans;
}
int main()
{
int arr[] = { 1, 2, 3, -5, -7 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << maxSumAfterPartition(arr, n);
return 0;
}
Python3
# Python 3 Program for the above approach
def maxSumAfterPartition(arr, n):
# Stores the positive elements
pos = []
# Stores the negative elements
neg = []
# Stores the count of 0s
zero = 0
# Sum of all positive numbers
pos_sum = 0
# Sum of all negative numbers
neg_sum = 0
# Iterate over the array
for i in range(n):
if (arr[i] > 0):
pos.append(arr[i])
pos_sum += arr[i]
elif(arr[i] < 0):
neg.append(arr[i])
neg_sum += arr[i]
else:
zero += 1
# Stores the difference
ans = 0
# Sort the positive numbers
# in ascending order
pos.sort()
# Sort the negative numbers
# in decreasing order
neg.sort(reverse=True)
# Case 1: Include both positive
# and negative numbers
if (len(pos) > 0 and len(neg) > 0):
ans = (pos_sum - neg_sum)
elif(len(pos) > 0):
if (zero > 0):
# Case 2: When all numbers are
# positive and array contains 0s
#Put all numbers in subset A and
#one 0 in subset B
ans = (pos_sum)
else:
# Case 3: When all numbers are positive
#Put all numbers in subset A except the
#smallest positive number which is put in B
ans = (pos_sum - 2 * pos[0])
else:
if (zero > 0):
# Case 4: When all numbers are
# negative and array contains 0s
# Put all numbers in subset B
# and one 0 in subset A
ans = (-1 * neg_sum)
else:
# Case 5: When all numbers are negative
# Place the largest negative number
# in subset A and remaining in B
ans = (neg[0] - (neg_sum - neg[0]))
return ans
if __name__ == '__main__':
arr = [1, 2, 3, -5, -7]
n = len(arr)
print(maxSumAfterPartition(arr, n))
# This code is contributed by ipg2016107.
输出
18
时间复杂度: O(NlogN)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。