leetcode 1029. Two City Scheduling

There are 2N people a company is planning to interview. The cost of flying the i-th person to city A is costs[i][0], and the cost of flying the i-th person to city B is costs[i][1].

Return the minimum cost to fly every person to a city such that exactly N people arrive in each city.

Example 1:

Input: [[10,20],[30,200],[400,50],[30,20]]
Output: 110
Explanation: 
The first person goes to city A for a cost of 10.
The second person goes to city A for a cost of 30.
The third person goes to city B for a cost of 50.
The fourth person goes to city B for a cost of 20.

The total minimum cost is 10 + 30 + 50 + 20 = 110 to have half the people interviewing in each city.

Note:

  1. 1 <= costs.length <= 100
  2. It is guaranteed that costs.length is even.
  3. 1 <= costs[i][0], costs[i][1] <= 1000

题目大意:

公司计划面试 2N 人。第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]。

返回将每个人都飞到某座城市的最低费用,要求每个城市都有 N 人抵达。

思路:采用贪心算法,按照每个人到A城市的费用从小到大排序,去前N个到A城市,虽然这个N个人到A城市的费用最低,但另外N个人到达B城市的费用大概率不是最低,导致加起来的总费用不是最低。所以应该联合起来考虑。每一个人都必须去一个城市,如何确定他应该去A还是B呢?考虑他去A,相对于去B城市能省多少钱,省的越多,最后总费用就越低。

以样例 [[10,20],[30,200],[400,50],[30,20]]为例,

p1: [10,20] -> 10-20=-10

p2: [30, 200] -> 30-200=-170

p3:[400,50] -> 400-50 = 350

p4:[30,20] -> 30-20 = 10

基于差值从小到大排序:-170,-10,10, 350 -> [[30,200],[10,20],[30,20],[400,50]],即排序后的前两个人选城市A,后两个人选城市B。

 1 class Solution {
 2 public:
 3     static bool cmp(const vector<int> &a, const vector<int> &b) {
 4         return (a[0] - a[1]) < (b[0] - b[1]);
 5     }
 6     int twoCitySchedCost(vector<vector<int>>& costs) {
 7         int N = costs.size() / 2;
 8         sort(costs.begin(), costs.end(), cmp);
 9         int cost = 0;
10         for (int i = 0; i < N; ++i) {
11             cost += costs[i][0];
12             cost += costs[i + N][1];
13         }
14         return cost;
15     }
16 };

时间复杂度:$O(nlogn)$

空间复杂度:$O(1)$


从另一个视角看,所有人都去A城市,需要安排N个人转到B城市,我们找到相较于去A城市,去B城市最省的N个人:

  所有人去A城市的总费用为10+30+400+30 = 470, 按照差值排序后,最后2个人分别能省350、10,因此安排这个两个人去B城市,最后总费用为470-350-10=110

 1 class Solution {
 2 public:
 3     int twoCitySchedCost(vector<vector<int>>& costs) {
 4         int N = costs.size() / 2;
 5         vector<int> diff(costs.size(), 0);
 6         int sum = 0;
 7         for (int i = 0; i < costs.size(); ++i) {
 8             sum += costs[i][0];
 9             diff[i] = costs[i][1] - costs[i][0];
10         }
11         sort(diff.begin(), diff.end());//默认从小到大排序,所以计算差值的时候用costs[i][1] - costs[i][0]
12         for (int i = 0; i < N; ++i) {
13             sum += diff[i];
14         }
15         return sum;
16     }
17 };

时间复杂度:$O(nlogn)$

空间复杂度:$O(n)$

原文地址:https://www.cnblogs.com/qinduanyinghua/p/13043050.html