Solution: Splitting the Pirate Loot

Solution for the 3-Partition Problem.

We'll cover the following

Solution

Let’s denote v1+v2++viv_1 + v_2 + ··· + v_i as sum(i)(i). Splitting the set of nn items evenly into three parts is possible only if their total value is divisible by three, i.e., sum(n)=3V(n) = 3V, where VV is an integer. Then, we need to partition nn numbers into three parts where the sum of numbers in each part is equal to VV. Instead of partitioning all nn items, let’s try to solve a smaller problem of partitioning the first ii items into parts of value s1,s2,s_1, s_2, and sum(i)s1s2sum(i) − s_1 − s_2. We define split(i,s1,s2)=split(i,s_1,s_2) = true if such partition is possible (and false, otherwise) and note that the pirates can fairly split the loot only if split(n,V,V)=split(n,V,V)= true.

Stop and think:

Given the first five items

36419\boxed{3}\boxed{6}\boxed{4}\boxed{1}\boxed{9}

split(5,4,13)=split(5,4,13) = true.

Find all other values split(5,s1,s2)split(5,s1,s2) equal to true.

Imagine that you have already constructed the binary two-dimensional array split(i1,s1,s2)split(i−1,s_1,s_2) for all possible values 0s1V0≤s_1 ≤V and 0s2V0 ≤ s_2 ≤ V . Can you use this array to construct the array split(i,s1,s2)split(i,s_1,s_2)?

Assume that split(i,s1,s2)=split(i,s_1,s_2) = true—that is, we can split the first ii numbers into three parts such that the sum of numbers in the first part is s1s_1 and the sum of numbers in the second part is s2s_2.

  • The ii-th number belongs to the first part. Then vis1v_i ≤ s_1. By taking it out of the first part, we will partition the first i1i − 1 numbers into three parts such that the sum of the first two parts is s1vis_1 − v_i and s2s_2, that is, split(i1,s1vi,s2)=split(i − 1, s_1 − v_i , s_2 ) = true.

  • The ii-th number belongs to the second part. Then vis1v_i ≤ s_1. Similarly to the previous case, vis2v_i ≤s_2 and split(i1,s1,s2vi)=split(i−1,s_1,s_2−v_i)= true.

  • The ii-th item belongs to the third part. Then, split(i1,s1,s2)=split(i−1,s_1,s_2)= true. This way, we compute the value of split(i,s1,s2)split(i,s_1,s_2) by looking at split(i1,s1vi,s2)split(i−1,s_1−v_i,s_2), split(i1,s1,s2vi)split(i−1,s_1,s_2−v_i), and split(i1,s1,s2)split(i−1,s_1,s_2).

The base case for this recurrence relation is: split(0,0,0)=split(0,0,0) = true and split(0,s1,s2)=split(0,s_1,s_2)= false if s1+s2>0s_1+s_2 >0.


 Split(v1,,vn)Split(v_1,\ldots,v_n):
 if v1++vnv_1 +\ldots+v_n is not divisible by 33:
 return false
 V(v1++vn)/3V ←(v_1+\ldots+v_n)/3
 splitsplit ← three-dimensional array of size (n+1)×(V+1)×(V+1)(n + 1) × (V + 1) × (V + 1)
 initialize all elements of splitsplit to false
 split[0][0][0]split[0][0][0] ← true
 for ii from 11 to nn:
 for s1s_1 from 00 to VV:
   for s2s_2 from 00 to VV:
    split[i][s1][s2]split[i1][s1][s2]split[i][s_1][s_2] ← split[i − 1][s_1][s_2]
    if s1vis_1 ≥ v_i:
     split[i][s1][s2]split[i][s1][s2]split[i][s_1][s_2] ← split[i][s_1][s_2] OR split[i1][s1vi][s2]split[i −1][s_1 −v_i][s_2]
    if s2vis_2 ≥ v_i:
     split[i][s1][s2]split[i][s1][s2]split[i][s_1][s_2] ← split[i][s_1][s_2] OR split[i1][s1][s2vi]split[i − 1][s_1][s_2 − v_i]
 return split[n][V][V]split[n][V ][V ]


The running time is O(nV2)O(nV^2).

Code

Level up your interview prep. Join Educative to access 70+ hands-on prep courses.