-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathminimum-array-sum.py
88 lines (80 loc) · 2.58 KB
/
minimum-array-sum.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Time: O(nlogn)
# Space: O(n)
# greedy, case works
# Reference: https://leetcode.com/problems/minimum-array-sum/solutions/6078002/o-n-log-n-greedy/
class Solution(object):
def minArraySum(self, nums, k, op1, op2):
"""
:type nums: List[int]
:type k: int
:type op1: int
:type op2: int
:rtype: int
"""
nums.sort()
left = next((i for i in xrange(len(nums)) if nums[i] >= k), len(nums))
right = next((i for i in xrange(len(nums)) if nums[i] >= 2*k-1), len(nums))
lookup, cnt = [False]*len(nums), 0
for j in reversed(xrange(right, len(nums))):
if not op1:
break
op1 -= 1
nums[j] = (nums[j]+1)//2
if op2:
op2 -= 1
nums[j] -= k
else:
j = right-1
for i in xrange(left, j+1):
if not op2:
break
op2 -= 1
if k%2 == 1 and nums[i]%2 == 0:
lookup[i] = True
nums[i] -= k
else:
i = j+1
for j in reversed(xrange(i, j+1)):
if not op1:
break
op1 -= 1
if k%2 == 1 and nums[j]%2 == 1:
cnt += 1
nums[j] = (nums[j]+1)//2
else:
j = i-1
arr = sorted((nums[idx], idx) for idx in xrange(i))
for _ in xrange(op1):
x, idx = arr.pop()
nums[idx] = (x+1)//2
if cnt and lookup[idx]:
cnt -= 1
nums[idx] -= 1
return sum(nums)
# Time: O(n * op1 * op2)
# Space: O(op1 * op2)
# dp
class Solution2(object):
def minArraySum(self, nums, k, op1, op2):
"""
:type nums: List[int]
:type k: int
:type op1: int
:type op2: int
:rtype: int
"""
dp = [[sum(nums)]*(op2+1) for _ in xrange(op1+1)]
for x in nums:
for i in reversed(xrange(op1+1)):
for j in reversed(xrange(op2+1)):
if i-1 >= 0:
dp[i][j] = min(dp[i][j], dp[i-1][j]-x+(x+1)//2)
if j-1 >= 0:
if x-k >= 0:
dp[i][j] = min(dp[i][j], dp[i][j-1]-x+(x-k))
if i-1 >= 0 and j-1 >= 0:
if x-k >= 0:
dp[i][j] = min(dp[i][j], dp[i-1][j-1]-x+((x-k)+1)//2)
if (x+1)//2-k >= 0:
dp[i][j] = min(dp[i][j], dp[i-1][j-1]-x+((x+1)//2-k))
return dp[op1][op2]