运行时间: 1060 ms
内存: 0.0 MB
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n = len(nums)//2
# dp0, dp2 = set([0]), set()
# for i in range(n):
# ndp0, ndp2 = set(), set()
# nd0, nd2 = abs(nums[2*i]-nums[2*i+1]), nums[2*i]+nums[2*i+1]
# for d in dp0:
# ndp0.update([d+nd0, abs(d-nd0)])
# ndp2.update([nd2+d, nd2-d])
# for d in dp2:
# ndp0.add(abs(nd2-d))
# ndp2.update([d+nd0, d-nd0])
# dp0, dp2 = ndp0, ndp2
# return min(dp0)
# # past 134/201
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n = len(nums)//2
# dp = defaultdict(set)
# dp[0] = set([0])
# for i in range(n):
# nd0, nd2 = abs(nums[2*i]-nums[2*i+1]), nums[2*i]+nums[2*i+1]
# ndp = defaultdict(set)
# for dn, dss in dp.items():
# mdn = 2*min(i+1, n-(i+1))
# for ds in dss:
# if dn==0: ndp[dn].update([abs(ds+nd0), abs(ds-nd0)])
# elif dn<=mdn: ndp[dn].update([ds+nd0, ds-nd0])
# if 0<=dn-2<=mdn: ndp[dn-2].add(abs(ds-nd2) if dn==2 else ds-nd2)
# if dn+2<=mdn:
# ndp[dn+2].add(ds+nd2)
# if dn==0: ndp[dn+2].add(nd2-ds)
# dp = ndp
# return min(dp[0])
# # past 134/201
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n = len(nums)//2
# dp = defaultdict(set)
# dp[0] = set([0])
# for i in range(2*n):
# ndp = defaultdict(set)
# for dn, dss in dp.items():
# for ds in dss:
# if dn>=1:
# ndp[dn-1].add(abs(ds-nums[i]) if dn==1 else ds-nums[i])
# if dn+1<=min(i+1, 2*n-(i+1)):
# ndp[dn+1].add(ds+nums[i])
# if dn==0: ndp[dn+1].add(nums[i]-ds)
# dp = ndp
# return min(dp[0])
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n = len(nums)//2
# dp = {0: [[0, 0], [0, 0]]}
# def _update_n1(dn, pm, nm, nu):
# pbit, mp = pm
# nbit, mn = nm
# npbit, nmp = 0, mp
# nnbit, nmn = 0, mn
# for i in range(mp):
# if pbit&(1<<i)==0: continue
# nds = i-nu
# if dn==1 or nds>=0:
# npbit |= 1<<abs(nds)
# nmp = max(nmp, abs(nds))
# else:
# nnbit |= 1<<abs(nds)
# nmn = max(nmn, abs(nds))
# for i in range(mn):
# if nbit&(1<<i)==0: continue
# nds = -i-nu
# if dn==1 or nds>=0:
# npbit |= 1<<abs(nds)
# nmp = max(nmp, abs(nds))
# else:
# nnbit |= 1<<abs(nds)
# nmn = max(nmn, abs(nds))
# return [npbit, nmp], [nnbit, nmn]
# # if dn+1<=min(i+1, 2*n-(i+1)):
# # ndp[dn+1].add(ds+nums[i])
# # if dn==0: ndp[dn+1].add(nums[i]-ds)
# def _update_p1(dn, pm, nm, nu):
# pbit, mp = pm
# nbit, mn = nm
# npbit, nmp = 0, mp
# nnbit, nmn = 0, mn
# for i in range(mp):
# if pbit&(1<<i)==0: continue
# nds = i+nu
# if nds>=0:
# npbit |= 1<<abs(nds)
# nmp = max(nmp, abs(nds))
# else:
# nnbit |= 1<<abs(nds)
# nmn = max(nmn, abs(nds))
# if dn==0:
# nds = nu-i
# for i in range(mn):
# if nbit&(1<<i)==0: continue
# for i in range(2*n):
# ndp = {}
# for dn, bits in dp.items():
# pm, nm = bits
# if dn>=1:
# pm, nm = ndp.get(dn-1, [0, 0])
# if dn==1: pm |= 1<<abs(ds-nums[i])
# else:
# pm, nm = _update(ds-nums[i], pm, nm)
# ndp[dn-1] = [pm, nm]
# if dn+1<=min(i+1, 2*n-(i+1)):
# pm, nm = ndp.get(dn+1, [0, 0])
# pm, nm = _update(ds+nums[i], pm, nm)
# if dn==0: pm, nm = _update(nums[i]-ds, pm, nm)
# ndp[dn+1] = [pm, nm]
# dp = ndp
# md = 0
# while dp[0][0]%2==0:
# md += 1
# dp[0][0] //= 2
# return md
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n, ss = len(nums)//2, sum(nums)
# ts = ss//2
# dp = [[ts, ts+1] for _ in range(n+1)]
# for l in range(1, 2*n+1):
# for k in range(1, min(l, n)+1):
# ns0, ns1 = dp[k-1][0]+nums[l-1], dp[k-1][1]+nums[l-1]
# if dp[k][0]<ns0<=ts: dp[k][0] = ns0
# if dp[k][1]<ns0<=ts+1: dp[k][1] = ns1
# return min(abs(ss-2*dp[-1][0]), abs(ss-2*dp[-1][1]))
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n, ss = len(nums)//2, sum(nums)
# dp = [ss for _ in range(n+1)]
# for l in range(1, 2*n+1):
# for k in range(1, min(l+n)+1):
# dp[k] = min(dp[k], abs(ss-2*(dp[k-1]+nums[l-1])))
# return dp[-1]
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n, ts = len(nums)//2, sum(nums)
# lns, rns = nums[:n], nums[n:]
# def _subset_sum(arr):
# dp = defaultdict(set)
# dp[0] = set([0])
# for i in range(len(arr)):
# ndp = defaultdict(set)
# for c in range(i+1):
# ndp[c].update(dp[c])
# ndp[c+1] = set([s+arr[i] for s in dp[c]])
# dp = ndp
# return dp
# def _find_peak(a, barr):
# # find the peak value of an array with unique numbers
# nb = len(barr)
# l, r = 0, nb-1
# while l<r:
# m = (l+r)//2
# s0, s1 = abs(ts-2*(a+barr[m])), abs(ts-2*(a+barr[m+1]))
# if s0>s1: l = m+1
# else: r = m
# return abs(ts-2*(a+barr[r]))
# ldss, rdss = _subset_sum(lns), _subset_sum(rns)
# md = sys.maxsize
# for i in range(n+1):
# lss, rss = ldss[i], rdss[n-i]
# sss = lss if len(lss)<len(rss) else rss
# bss = rss if len(lss)<len(rss) else lss
# sss = sorted(sss)
# for a in bss:
# md = min(md, _find_peak(a, sss))
# del ldss[i], rdss[n-i]
# return md
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# n, ts = len(nums)//2, sum(nums)
# lns, rns = nums[:n], nums[n:]
# lts, rts = sum(lns), sum(rns)
# def _subset_sum(arr):
# nn, dp = len(arr), defaultdict(set)
# dp[0] = set([0])
# for i in range(nn):
# ndp = defaultdict(set)
# for c in range(min(i, nn//2)+1):
# ndp[c].update(dp[c])
# ndp[c+1] = set([s+arr[i] for s in dp[c]])
# dp = ndp
# return dp
# def _find_peak(a, barr, bts):
# # find the peak value of an array with unique numbers
# nb = len(barr)
# l, r = 0, nb-1
# while l<r:
# m = (l+r)//2
# s0, s1 = abs(ts-2*(a+bts-barr[m])), abs(ts-2*(a+bts-barr[m+1]))
# if s0>s1: l = m+1
# else: r = m
# return abs(ts-2*(a+bts-barr[r]))
# ldss, rdss = _subset_sum(lns), _subset_sum(rns)
# md = abs(lts-rts)
# for i in range(n//2+1):
# lss, rss = ldss[i], rdss[i]
# if len(lss)<len(rss):
# sss, bss, sts = sorted(lss), rss, lts
# else:
# sss, bss, sts = sorted(rss), lss, rts
# for a in bss:
# md = min(md, _find_peak(a, sss, sts))
# del ldss[i], rdss[i]
# return md
class Solution:
def minimumDifference(self, nums: List[int]) -> int:
n, ts = len(nums)//2, sum(nums)
lns, rns = nums[:n], nums[n:]
lts, rts = sum(lns), sum(rns)
def _subset_sum(arr):
nn, dp = len(arr), defaultdict(set)
dp[0] = set([0])
for i in range(nn):
ndp = defaultdict(set)
for c in range(min(i, nn//2)+1):
ndp[c].update(dp[c])
ndp[c+1] = set([s+arr[i] for s in dp[c]])
dp = ndp
return dp
ldss, rdss = _subset_sum(lns), _subset_sum(rns)
md = abs(lts-rts)
for i in range(n//2+1):
lss, rss = ldss[i], rdss[i]
if len(lss)<len(rss): sss, bss, sts = sorted(lss), rss, lts
else: sss, bss, sts = sorted(rss), lss, rts
for a in bss:
targ_rs = sts - (ts/2 - a)
bti = bisect_right(sss, targ_rs)
for j in [bti-1, bti]:
if j>=len(sss): continue
md = min(md, abs(ts-2*(a+sts-sss[j])))
del ldss[i], rdss[i]
return md
# class Solution:
# def minimumDifference(self, nums: List[int]) -> int:
# N = len(nums) // 2 # Note this is N/2, ie no. of elements required in each.
# def get_sums(nums): # generate all combinations sum of k elements
# ans = {}
# N = len(nums)
# for k in range(1, N+1): # takes k element for nums
# sums = []
# for comb in combinations(nums, k):
# s = sum(comb)
# sums.append(s)
# ans[k] = sums
# return ans
# left_part, right_part = nums[:N], nums[N:]
# left_sums, right_sums = get_sums(left_part), get_sums(right_part)
# ans = abs(sum(left_part) - sum(right_part)) # the case when taking all N from left_part for left_ans, and vice versa
# total = sum(nums)
# half = total // 2 # the best sum required for each, we have to find sum nearest to this
# for k in range(1, N):
# left = left_sums[k] # if taking k no. from left_sums
# right = right_sums[N-k] # then we have to take remaining N-k from right_sums.
# right.sort() # sorting, so that we can binary search the required value
# for x in left:
# r = half - x # required, how much we need to add in x to bring it closer to half.
# p = bisect.bisect_left(right, r) # we are finding index of value closest to r, present in right, using binary search
# for q in [p, p-1]:
# if 0 <= q < len(right):
# left_ans_sum = x + right[q]
# right_ans_sum = total - left_ans_sum
# diff = abs(left_ans_sum - right_ans_sum)
# ans = min(ans, diff)
# return ans