0

I am trying to solve this popular problem:

"Given an integer array, divide the array into two subsets, A and B, while respecting the following conditions.

  1. the intersection of A and B is null.

  2. the union A and B is equal to the original array.

  3. the number of elements in subset A is minimal.

  4. the sum of A's elements is greater than the sum of B's elements.

Return the subset A in increasing order, where the sum of A's elements is greater than the sum of B's elements. If more than one subset exists, return the one with the maximal sum."

I found several solutions online but none of them solve it when the test case is [2,2,2,5]

I wrote the following code:

def subsetA(nums):
    nums.sort(reverse=True)
    subset_a = []
    sum_a = 0
    sum_b = 0

    for num in nums:
        if sum_a <= sum_b:
            sum_a += num
            subset_a.append(num)
        else:
            sum_b += num

    return sorted(subset_a)

This solution works for a lot of cases but it doesn't work for the test case I mentioned above.

The answer should be [2,2,2]. But i cannot think of any solution that will return that answer.

How can I improve this code?

2
  • also, we talk about "sublists" here, not "subsets", right? Subsets of [2,2,2,5] would be only {2}, {5} and {2,5}. Commented Dec 16, 2023 at 0:55
  • If it is [2,5], then it violates condition 1. Commented Dec 16, 2023 at 4:49

2 Answers 2

1

One way to solve this is as a linear program with binary variables. Suppose the array is held by the variable arr, where arri is the value of the element at index i.

First define the binary variables.

xi equals 1 if arri is assigned to A, and equals 0 if it is assigned to B

The objective (function) and constraints are as follows::

min ∑ixi

subject to:

iarrixi >= ∑iarri(1-xi) + t

t is a pre-defined tolerance to ensure that a strict inequality is achieved (linear programs cannot have strict inequalities).

Notice that 1-xi equals 1 if arri is assigned to B.

The constraint needs to be rearranged as follows.

iarrixi >= (∑iarri + t)/2


An integer linear programming (ILP) package can then be used to obtain optimal values for the variables.

Sign up to request clarification or add additional context in comments.

Comments

0

You are using greedy algorithm, it does not guarantee the best solution. If sum of list is reliable, you can apply dynamic programming.

k-th entry of list a contains tuple (last index, number of items to compose sum k).

We fill table a: for every value n from nums check a entries whether a) sum k might be composed with n + k-n sum b) number of items for this sum is better than before

Then look for the smallest number of items in the second half of the table - it is the best sum for given condition. Then we retrieve used items.

def bestsubsetsum(nums):
    l = len(nums)
    S = sum(nums)
    nums.sort()
    a =[(0,l+1)]*(S+1)
    a[0] = (-1,0)

    for j, n in enumerate(nums):
        for k in range(S, n-1,-1):
            if a[k-n][0] and a[k-n][1]+1 < a[k][1]:
                a[k] = (j+1, a[k-n][1]+1)
    #print(a)

    a[0] = (-1, l+1)
    imin = 0
    for k in range(S//2+1,S+1):
        if a[k][1] <= a[imin][1]:
            imin = k
    A = []
    while imin:
        A.insert(0, nums[a[imin][0]-1])
        imin -= nums[a[imin][0]-1]
    return A


print(bestsubsetsum([3,7,12,1]))
print(bestsubsetsum([2,2,2,5]))
print(bestsubsetsum([2,4,3,7,3,7,3]))
print(bestsubsetsum([2,4,3,9,3,7,3]))

>>
[12]
[2, 5]
[4, 7, 7]
[7, 9]

5 Comments

This solution doesn't work. print(bestsubsetsum([1,1,1,2])) returns [1,2]. This is wrong, it should retain [1,1,1,2]
No, this is correct solution. 1,2 is the shortest subset with sum larger than rest
For input [2,2,2,5], subset a contains [2,5] and b contains [2, 2]. This breaks condition #1. The correct answer should be a = [2,2,2] and b= [5].
It seems that "set" term is used incorrectly , because we cannot build source array from true sets in many cases
@Jonathan Why should it return [1,1,1,2], why not [1,1,1]?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.