|
| 1 | +#!/usr/bin/env python |
| 2 | +''' |
| 3 | +Leetcode: 3Sum Closest |
| 4 | +
|
| 5 | +Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution. |
| 6 | +
|
| 7 | + For example, given array S = {-1 2 1 -4}, and target = 1. |
| 8 | + The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). |
| 9 | +
|
| 10 | +''' |
| 11 | +from __future__ import division |
| 12 | +import random |
| 13 | + |
| 14 | +### DP? Given a list L |
| 15 | +# S(i, k, target) = True if we can find k elements among L[:i] to sum up to target |
| 16 | +# S(i, k, target) = S(i-1, k-1, target-L[i-1]) or S(i-1, k, target) |
| 17 | +def sum_closest(L, num_k, target): |
| 18 | + import math |
| 19 | + n = len(L) |
| 20 | + S = {} |
| 21 | + prev = {} |
| 22 | + max_t = sum([x for x in L if x > 0]) |
| 23 | + min_t = sum([x for x in L if x <= 0]) |
| 24 | + print 'target range: [%d, %d]' %(min_t, max_t) |
| 25 | + |
| 26 | + # Initialization: |
| 27 | + # S(0,any,any) = False |
| 28 | + # S(any,0,any) = False |
| 29 | + # S(any,0,0) = True |
| 30 | + for i in range(n+1): |
| 31 | + for t in range(min_t, max_t+1): |
| 32 | + S[(i,0,t)] = False |
| 33 | + for k in range(num_k+1): |
| 34 | + for t in range(min_t, max_t+1): |
| 35 | + S[(0,k,t)] = False |
| 36 | + for i in range(n+1): |
| 37 | + S[(i,0,0)] = True |
| 38 | + |
| 39 | + for i in range(1,n+1): |
| 40 | + for k in range(1,num_k+1): |
| 41 | + for t in range(min_t, max_t+1): |
| 42 | + with_elem = S[(i-1,k-1,t-L[i-1])] if min_t <= t-L[i-1] <= max_t else False |
| 43 | + without_elem = S[(i-1,k,t)] |
| 44 | + |
| 45 | + S[(i,k,t)] = with_elem or without_elem |
| 46 | + if with_elem: prev[(i,k,t)] = (i-1,k-1,t-L[i-1]) |
| 47 | + elif without_elem: prev[(i,k,t)] = (i-1,k,t) |
| 48 | + |
| 49 | + # min{|t-target| for S[(n,num_k,t)] == True} |
| 50 | + cands = [t for t in range(min_t, max_t+1) if S[(n,num_k,t)]] |
| 51 | + output_t = min(cands, key=lambda x:math.fabs(x-target)) |
| 52 | + |
| 53 | + # print out |
| 54 | + output = [] |
| 55 | + i,k,t = n,num_k,output_t |
| 56 | + while (i,k,t) in prev: |
| 57 | + next_i,next_k,next_t = prev[(i,k,t)] |
| 58 | + if next_k == k-1: output.append(L[next_i]) |
| 59 | + i,k,t = next_i,next_k,next_t |
| 60 | + print 'output:', output, 'sum(output):', sum(output) |
| 61 | + return output |
| 62 | + |
| 63 | + |
| 64 | +if __name__ == '__main__': |
| 65 | + sum_closest([-1, 2, 1, -3, 6], 2, 2) |
| 66 | + |
| 67 | + |
0 commit comments