原题
公司计划面试 2N 人。第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]。
返回将每个人都飞到某座城市的最低费用,要求每个城市都有 N 人抵达。
示例:
输入:[[10,20],[30,200],[400,50],[30,20]]
输出:110
解释:
第一个人去 A 市,费用为 10。
第二个人去 A 市,费用为 30。
第三个人去 B 市,费用为 50。
第四个人去 B 市,费用为 20。
最低总费用为 10 + 30 + 50 + 20 = 110,每个城市都有一半的人在面试。
提示:
- 1 <= costs.length <= 100
- costs.length 为偶数
- 1 <= costs[i][0], costs[i][1] <= 1000
思路
本题也是典型的运用贪心算法的题目。我们首先只关注局部,优先选择两地之间价格最低的。
但是这样做可能造成去A,B两个城市人数不平等。我们需要对两个数组进行排序。排序的规则是两个城市价格差值的绝对值从小到大排序。因为当价格差值最小时,对总价格影响也是最小的。
举一个例子
const a = [[10000, 10001], [100, 110], [1, 20]];
const b = [[200, 100]];
如果将20分配给b。b的总价是100 + 20 === 120; a的总价是10000 + 100 === 10100; a和b的总价是10100 + 120 === 10220
如果将10001分配个b。b的总价是10001 + 100 === 10101; a的总价是100 + 1 === 101; a和b的总价是10101 + 101 === 10202
我们判断A和B城市之间人数的多少,使用价格差值绝对值较小的人,去填充人数较少的城市。即可得到最低的费用。
代码
var twoCitySchedCost = function(costs) {
let aCost = [];
let bCost = [];
let aPeople = 0;
let bPeople = 0;
const sum = (costs, type) => {
let s = 0;
costs.forEach(cost => {
if (type === "A") {
s += cost[0];
} else {
s += cost[1];
}
});
return s;
};
for (let i = 0; i < costs.length; i++) {
if (costs[i][0] > costs[i][1]) {
bPeople += 1;
bCost.push(costs[i]);
} else {
aPeople += 1;
aCost.push(costs[i]);
}
}
aCost = aCost.sort((a, b) => Math.abs(a[0] - a[1]) - Math.abs(b[0] - b[1]));
bCost = bCost.sort((a, b) => Math.abs(a[0] - a[1]) - Math.abs(b[0] - b[1]));
if (aPeople > bPeople) {
bCost = [...bCost, ...aCost.splice(0, costs.length / 2 - bPeople)]
} else if (aPeople < bPeople) {
aCost = [...aCost, ...bCost.splice(0, costs.length / 2 - aPeople)]
}
return sum(aCost, "A") + sum(bCost, "B");
};