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

Vite + Vue + Bun on Rails

Vue.js is one of frontend frameworks gaining popularity among rapidly emerging JavaScript technologies. The combination of Vue.js and Rails is becoming more popular as well, however, Vue.js development on Rails is not so straightforward. The reason would be that Vue.js relies on Vite for a development environment such as HMR (Hot Module Replacement) and bundling.

Bun + React on Rails

In the frontend world, new technologies keep emerging rapidly these years. Still, React is a well-established and very popular frontend framework, Vue.js, Svelte, Astro and more frameworks are gaining popularity. Not just the frameworks, tools for a transpiler/bundler or sort are also under a rapid development. In JavaScript domain, esbuild, rollup, vite and some more are out.

Ruby on Rails Secrets Management

A web application needs various kinds of values, params and etc which should not be revealed to the public, say GitHub repo. For example, API keys, tokens, passwords, and endpoints, all those should be kept secret. Another important factor is that such secrets should be shared among the team members. Additionally, all those secrets should come along with the deployment.