2

Today, while practicing some Algorithm questions I found an interesting question. The question is

You have to divide 1 to n (with one missing value x ) into two equal halfs such that sum of the two halfs are equal.

Example:

If n = 7 and x = 4

The solution will be {7, 5} and {1, 2, 3, 6}

I can answer it with brute force method but i want an efficient solution Can any one help me out?

  • 2
    You should check if you are able to reach the (Sum(1 to n) - x) /2. with the number without including x. It is the same as the sub-set sum. Also the answer to n = 7 and x = 4 is [7, 5], [1, 2, 3, 6] – thebenman Jan 11 '18 at 05:27
  • Thanx ,i corrected that typo. – user8043557 Jan 11 '18 at 07:41
  • I have not tried to proove it but it may be that a greedy algorithm always works (if there is a solution at all). You should spend some time investigating it this direction. – Henry Jan 11 '18 at 07:56

2 Answers2

0

If the sum of the elements 1→N without x is odd then there is no solution.

Otherwise you can find your solution in O(N) with balanced selection.

4 in a row

First let us consider that any sequence of four contiguous numbers can be split in two sets with equal sum given that:

[x, x+1, x+2, x+3] → [x+3, x];[x+2, x+1]

Thus selecting them and placing them in sets A B B A balances sets A and B.

4 across

Moreover, when we have two couples across an omitted value, it can hold a similar property:

[x-2, x-1, x+1, x+2] → [x+2, x-2]; [x+1, x-1]

so still A B B A

At this point we can fix the following cases:

  • we have a quadruplet: we split it as in case 1
  • we have 2 numbers, x and other 2 numbers: we split as in case 2

Alright, but it can happen we have 3 numbers, x and other 3 numbers, or other conditions. How can we select in balanced manner anyway?

+2 Gap

If we look again at the gap across x:

[x-1, x+1]

we can notice that somehow if we split the two neighbors in two separate sets we must balance a +2 on the set with bigger sum.

Balancing Tail

We can do this by using the last four numbers of the sequence:

[4 3 2 1] → [4, 2] ; [3, 1] → 6 ; 4

Finally we have to consider that we might not have one of them, so let's build the other case:

[3 2 1] → [2] ; [3, 1] → 2 ; 4

and let us also realize we can do the very same at the other end of the sequence with an A B A B (or B A B A) pattern - if our +2 stands on B (or A);

4 across +

It is amazing that 4 across still holds if we jump h (odd!) numbers:

[x+3, x+2, x-2, x-3] → [x+3, x-3]; [x+2, x-2]

So, exploring the array we can draw the solution step by step

An example:

11 10 9 8 7 6 5 4 3 2 1

the sum it's even, so x can be only an even number:

x = 10
11 - 9 | 8 7 6 5 | 4 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
 A   B   A B B A   B A B A

x = 8
11 10 | 9 - 7 | 6 5 | 4 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
 a  b   A   B | b a | B A B A

x = 6
11 10 9 8 | 7 - 5 | 4 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
 A  B B A   A   B   A B B B

x = 4 we have no balancing tail - we have to do that with head
11 10 9 8 | 7 6 | 5 - 3 | 2 1 → (balancing head) (4 across +) (+2 gap)
 A  B A B   A B | b   a | B A

x = 2
11 10 9 8 | 7 6 5 4 | 3 - 1 → (balancing head) (4 in a row) (+2 gap)
 A  B A B   A B B A   B   A

It is interesting to notice the symmetry of the solutions. Another example.

10 9 8 7 6 5 4 3 2 1

the sum it's odd, so x can be only an odd number, and the number of elements now is odd.

x = 9
10 - 8 | 7 6 5 4 | 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
 A   B   A B B A   B A B

x = 7
10 9 | 8 - 6 | 5 4 | 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
 a b | A   B | b a   B A B

x = 5
10 9 8 7 | 6 - 4 | 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
 A B B A   A   B   B A B

x = 3
10 9 8 7 | 6 5 | 4 - 2 | 1 → (balancing head) (4 across + virtual 0) (+2 gap)
 A B A B   B A | a   b | A

x = 1
10 9 8 7 | 6 5 4 3 | 2 → (balancing head) (4 in a row) (+2 gap virtual 0)
 A B A B   A B B A   B 

Finally it is worth to notice we can switch from A to B whenever we have a full balanced segment (i.e. 4 in a row or 4 across)

Funny said - but the property requesting the sum([1 ... N]-x) to be even makes the cases quite redundant if you try yourself.


I am pretty sure this algorithm can be generalized - I'll probably provide a revised version soon.

Fabio Veronese
  • 7,726
  • 2
  • 18
  • 27
0

This problem can be solved by wrapping the standard subset sum problem of dynamic programming with preprocessing steps. These steps are of O(1) com

Algorithm (n, x):

  1. sum = n * (n+1) / 2
  2. neededSum = sum - x
  3. If (neededSum % 2 != 0): return 0

  4. create array [1..n] and remove x from it

  5. call standard subsetsum(arr, 0, neededSum/2, [])

Working python implementation of subsetsum algorithm - printing all subsets is given below.

def subsetsum(arr, i, sum, ss):
    if i >= len(arr):
        if sum == 0:
            print ss
            return 1
        else:
            return 0

    ss1 = ss[:]
    count = subsetsum(arr, i + 1, sum, ss1)
    ss1.append(arr[i])
    count += subsetsum(arr, i + 1, sum - arr[i], ss1)
    return count


arr = [1, 2, 3, 10, 5, 7]
sum = 14
a = []
print subsetsum(arr, 0, sum, a)

Hope it helps!

arunk2
  • 2,246
  • 3
  • 23
  • 35