Neeldhara
  • About
  • Research
    • Overview
    • People
    • Publications
    • Surveys
  • Teaching
    • Courses
    • Materials
  • Lists
    • Puzzles
    • Bookmarks
  • Exposition
    • Talks
    • Videos
  • Events
  • Blog

2. Subset Sum

  • Advanced Algorithms
    • Flows
    • Intractability
    • Approximation Algorithms
    • Randomized Algorithms
    • Greedy Algorithms
      • 1. Storing Files on a Tape
      • 2. A Scheduling Problem
      • 3. Stable Matchings
    • Matroids
      • 1. The Motivation
      • 2. The Definition
      • 3. Greedy Works!
      • 4. Scheduling with Deadlines
    • Dynamic Programming
      • 1. Longest Increasing Subsequence
      • 2. Subset Sum
      • 3. Set Cover
      • 4. Optimal BSTs
      • 5. Maximum Independent Set on Trees

On this page

  • The Problem
  • The Solution

2. Subset Sum

algonotes
lecturenotes
Published

May 16, 2023

Acknowledgements

Some of this material is borrowed from Jeff Erickson’s chapters on Recursion, Backtracking, and Dynamic Programming. Check them out for a more detailed comparison between recursive and memoized implementations.

The Problem

  • The Subset Sum takes as input an array XXX of nnn positive integers and a target Y>0Y > 0Y>0.
  • The output is YES if there is a subset of the array X[1..n]X[1 .. n]X[1..n] that sums to YYY, and NO otheriwse.

The Solution

What are the fragments (AKA, what do we want to store)?

Let us try to project this problem on a prefix of the input array and a generic target.

For 1≤i≤n1 \leq i \leq n1≤i≤n and 1≤j≤Y1 \leq j \leq Y1≤j≤Y, let:

$T[i,j] = $ TRUE if some subset of X[1,…,i]X[1,\ldots,i]X[1,…,i] sums to jjj, and FALSE otherwise.

The TTT-values are our fragments.

Are the fragments going to be useful (AKA, where is the final answer)?

Indeed, when the projection covers the original input, we are done! So the answer we are looking for is the value of T[n,Y]T[n,Y]T[n,Y].

Do we have a kickstart (AKA, what are the base cases)?

Note that:

T[1,j]T[1,j]T[1,j] is TRUE if and only if X[1]=jX[1] = jX[1]=j.

How do the fragments come together (AKA, how do we compute the values that we have agreed to store)?

If A[i]>jA[i] > jA[i]>j: then T[i,j]T[i,j]T[i,j] is TRUE if and only if (T[i−1,j]T[i-1,j]T[i−1,j]) is TRUE. Indeed, A[i]A[i]A[i] cannot participate in any solution here, since the array XXX only has positive integers, so we piggy back on whether a sum of jjj can be obtained from the subarray up to X[1,…,i−1]X[1,\ldots,i-1]X[1,…,i−1].

If A[i]=jA[i] = jA[i]=j: the return TRUE already, we have a solution comprising just of A[i]A[i]A[i] and it is our lucky day!

Otherwise: T[i,j]T[i,j]T[i,j] is TRUE if and only if (T[i−1,j−A[i]]∨T[i−1,j]T[i-1,j-A[i]] \lor T[i-1,j]T[i−1,j−A[i]]∨T[i−1,j]) is TRUE. Here, we take the best of both worlds by speculating on whether A[i]A[i]A[i] contributes to the solution or not. If it does, we update the target to j−A[i]j - A[i]j−A[i] — and notice that this is a legitimate index to ping since j>A[i]j > A[i]j>A[i]. If it does not, then as in the first situation, we fall back entirely on A[1,…,i]A[1,\ldots,i]A[1,…,i] to carry the burden of producing a solution. If netiher of these scenarios pan out, then observe that there is no solution at all.

Can we put the pieces together without getting stuck (AKA, are the dependencies in step #4 acyclic)?

It is straightforward to check that these dependencies are indeed acyclic.


© 2022 • Neeldhara Misra • Credits •

 

Corrections? Please leave a comment here or a PR in this repository, thanks!

I’d rather be a failure at something I love than a success at something I hate.

George Burns

You live and you learn — at any rate, you live.

Douglas Adams

A problem worthy of attack proves its worth by fighting back.

Paul Erdos

×