K Partition Problem

Published: May 23, 2017

Let’s think how we can divide an array of integers into K fair amount groups. The problem description is: given an array of integers, divide into k subarrays so that the differences of sum of each subarray will be minimized. Keep the order of the given array.

For example,


given: [1, 2, 3, 4, 5, 6, 7, 8]

k = 3: [[1, 2, 3, 4, 5], [6, 7], [8, 9]]
k = 4: [[1, 2, 3, 4], [5, 6], [7, 8], [9]]

This is called the linear parition, k-partition problem or, simply, partition problem. Despite the simple problem description, it is quite hard to solve. Spent some amount of time, finally, I could figure out how to solve this problem. Thinking its difficulty, this should be a good entry. For that reason, I’m going to write down a memo here.

The idea

The problem is well described in the document, The Partition Problem . Also, the first answer of this Quora question is a good one to understand how to solve. After reading those, what I can explain by my own words is below.

This is a dynamic programming problem. The states to keep track are optimum ways of partitioning, which will be saved in an auxiliary table. Suppose the auxiliary table is M[n][k] (n: size of given array, k: number of partitions), each element of M[i][j](i’th element, j paritions) will be computed by minimizing the maximum sum of partition when the given array is divided into j starting from index i.


given: {s[0], s[1], ... , s[n-1]}

M[i][j] = min (max (M[x][j - 1], s[i] + s[i+1] + ... + s[x]));

x: from 0 to i-1

To avoid calculate partial sums repeatedly, the algorithm calculates a prefix sum. The prefix sum of index i is caclulate from the sum to the index i - 1.


sum[i] = sum[i - 1] + s[i]

To compute sum from i to m is same as sum[m] - sum[i - 1]. So, repeatedly calculating same sums will be eliminated.

Java code

The code consists from two parts: build auxiliary tables to form partitions and reconstruct partitions. While partitioning, the algorithm uses one more table for divisers as described in the lecture note Applications of Dynamic Porgramming. The diviser table will be used to reconstruct the partitions.

The code returns the result:

[[1, 2, 3, 4, 5], [6, 7], [8, 9]]
[[1, 2, 3, 4, 5, 6], [7, 8, 9]]
[[1, 2, 3, 4], [5, 6], [7, 8], [9]]
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
[[1, 1, 1, 1], [1, 1, 1, 1, 1]]
[[1, 1, 1, 1], [1, 2, 2], [2, 2]]
[[1, 1, 1, 1, 1, 2], [2, 2, 2]]

Resources

Latest Posts

Application Development by Rails Action Cable

The previous two blog posts introduced WebSocket and how to implement a WebSocket application on Ruby on Rails. This blog post digs deeper. It is a memo on creating a more realistic application by Action Cable.

Real-time App on Rails by Action Cable

The previous blog post, WebSocket on Rails by Action Cable, focused on WebSocket as a protocol. As in the previous post, by default, Rails app responds to WebSocket connection requests without any hassle. However, other than connecting and sending ping frames, it doesn’t do anything. This blog post focuses on an application side and explains how we can create a full-duplex, bidirectional app.

WebSocket on Rails by Action Cable

In the web application domain, we hear some protocol names. Absolutely, HTTP or HTTPS is the most famous protocol that all web developers know. Although there’s a mechanism of Keep-Alive, a single request/response sequence with a single client/server is all done by HTTP. The client initiates the HTTP request to the server. Once the client receives the HTTP response from the server, communication finishes. As far as HTTP is used, the server just waits and waits. Only when the request comes in, the server can send back some data to the client. This communication style is surprisingly capable of doing many things, so most web applications are satisfied with HTTP.