每日題。最近真的很greedy,而且我竟然五分鐘就直接想出正解,這就是所謂的題感吧。

題目

有一間公司準備要面試2N個人,分別讓N個人在城市a,N個人在城市b。
costs二維陣列代表第i人飛往城市a和b的成本,求如何分配才能使所有人的移動成本最小化,並回傳最小成本。

解法

一定要靠排序,但是怎麼排?我想先把往a機會成本低的排到前面,且往b的成本越高,越優先排到a去。所以排序key為b-a。
排完後,前N個讓他飛到a去,後面N個飛到b去,全部加起來就是答案。

紀錄一下,本來key有點冗餘,改了幾次,才簡化成現在版本,其實都是相同意思。

第一版
key=lambda x:(x[0]-x[1],-abs(x[0]-x[1]))
第二版
key=lambda x:(x[0]-x[1],-x[1])
現在版
key=lambda x:(x[0]-x[1])

class Solution:
    def twoCitySchedCost(self, costs: List[List[int]]) -> int:
        N=len(costs)//2
        costs.sort(key=lambda x:(x[0]-x[1]))
        ans=0
        for i in range(N):
            ans+=costs[i][0]+costs[i+N][1]
                
        return ans

看到人家滿有趣的解法,但是速度比較慢一些。
首先預設全部人飛往a,並將b和a的差值存到refund裡面,當作是改飛b的價差,多退少補。
把refund排序後,再把前N的差額最小的加上去。

costs [10,20] [30,200] [400,50] [30,20]
全部飛a 10 30 400 30
改飛b差額 多10塊 多180 退350 退10

全a成本=10+30+400+30=470,選退錢最多的前N個,退350+退10,共退360,答案為470-360=110。

class Solution:
    def twoCitySchedCost(self, costs: List[List[int]]) -> int:
        N=len(costs)//2
        refund=[]
        ans=0
        for a,b in costs:
            ans+=a
            refund.append(b-a)
            
        refund.sort()
        for i in range(N):
            ans+=refund[i]
            
        return ans