-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathminimum-cost-to-make-array-equal.py
93 lines (80 loc) · 2.43 KB
/
minimum-cost-to-make-array-equal.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
89
90
91
92
93
# Time: O(nlogn)
# Space: O(n)
import itertools
# math, binary search
class Solution(object):
def minCost(self, nums, cost):
"""
:type nums: List[int]
:type cost: List[int]
:rtype: int
"""
def f(x):
return sum(abs(y-x)*c for y, c in itertools.izip(nums, cost))
def check(x, t):
return sum(c for y, c in itertools.izip(nums, cost) if y <= x) >= t
idxs = range(len(nums))
idxs.sort(key=lambda x: nums[x])
left, right = 0, len(idxs)-1
total = sum(cost)
median = (total+1)//2
while left <= right:
mid = left+(right-left)//2
if check(nums[idxs[mid]], median):
right = mid-1
else:
left = mid+1
return f(nums[idxs[left]])
# Time: O(nlogn)
# Space: O(n)
import itertools
# binary search
class Solution2(object):
def minCost(self, nums, cost):
"""
:type nums: List[int]
:type cost: List[int]
:rtype: int
"""
def f(x):
return sum(abs(y-x)*c for y, c in itertools.izip(nums, cost))
def check(x):
return x+1 == len(idxs) or f(nums[idxs[x]]) < f(nums[idxs[x+1]])
idxs = range(len(nums))
idxs.sort(key=lambda x: nums[x])
left, right = 0, len(idxs)-1
while left <= right:
mid = left+(right-left)//2
if check(mid):
right = mid-1
else:
left = mid+1
return f(nums[idxs[left]])
# Time: O(nlogn)
# Space: O(n)
# prefix sum
class Solution3(object):
def minCost(self, nums, cost):
"""
:type nums: List[int]
:type cost: List[int]
:rtype: int
"""
idxs = range(len(nums))
idxs.sort(key=lambda x: nums[x])
prefix = [0]*(len(cost)+1)
left = 0
for i in xrange(len(cost)):
if i-1 >= 0:
left += prefix[i]*(nums[idxs[i]]-nums[idxs[i-1]])
prefix[i+1] = prefix[i]+cost[idxs[i]]
result = float("inf")
suffix = right = 0
for i in reversed(xrange(len(cost))):
if i+1 < len(idxs):
right += suffix*(nums[idxs[i+1]]-nums[idxs[i]])
result = min(result, left+right)
if i-1 >= 0:
left -= prefix[i]*(nums[idxs[i]]-nums[idxs[i-1]])
suffix += cost[idxs[i]]
return result