如何处理基于排序的算法/理解代码背后的直觉?



我一直被困在一个算法问题上,我需要帮助才能取得进展。问题陈述如下。

问题定义:

公司计划面试的人2Ni-th人飞往城市A的费用是costs[i][0],而i-th人飞往城市B的费用是costs[i][1]

返回将每个人飞往一个城市的最低成本,以便每个城市正好N人到达。

输入:[[10,20],[30,200],[400,50],[30,20]]

输出:110

我已经看到了一些解决方案,它们涉及排序。

但是,我无法获得直觉。

有人可以向我解释如何解决这个问题吗?

这是我找到的示例解决方案:

public int twoCitySchedCost(int[][] costs) {
Comparator<int[]> comparator = (a, b) -> Math.abs(b[0] - b[1]) - Math.abs(a[0] - a[1]);
Arrays.sort(costs, comparator);
int N = costs.length / 2,
c1 = 0,// counter for the station A
c2 = 0,// counter for the station B
ans = 0,
i = 0;
while (i < 2 * N) {
if ((costs[i][0] <= costs[i][1] && c1 < N) || c2 == N) {
ans += costs[i++][0];
c1++;
} else {
ans += costs[i++][1];
c2++;
}
}
return ans;
}

让我们首先回顾一下这个算法在做什么。它根据每个人前往城市 A 与城市 B 的费用之间的差异对每个人进行排序。例如,如果人员 X 前往城市 A 和 B 的成本分别为 1 和 100,而人员 Y 前往城市 A 和 B 的成本分别为 49 和 50,则人员 X 在排序顺序中将比人员 Y 更早出现。我会尝试在比较器中插入一些示例来实现这一点。

接下来,算法贪婪地(意思是不需要对后来的人有远见(按照排序列表的顺序为每个人提供更便宜的城市。这种情况一直持续到一个城市"满员",即有 N 个人被分配到它,此时其他人都被分配到另一个城市。这发生在 while 循环和两个条件语句中。你能看到这个逻辑是如何发挥作用的吗?

最后,它引出了一个问题,为什么这个解决方案是有效的。请注意,如果我们取消了每个城市必须有N个人去的限制,那么最好的解决方案当然是将每个人送到他们更便宜的城市。但是,鉴于此限制,这并不总是可行的。每当有人不访问他们的最低成本城市时,他们就会偏离让每个人都去他们更便宜的城市的最低解决方案。也就是说,它们与城市A和城市B之间的成本差异的绝对值完全偏离。因此,我们考虑给那些成本差异大的人他们的首选是有道理的(否则,如果他们不得不偏离,成本的变化对他们来说将是最大的(。因此,这就是为什么我们贪婪地按照这种排序顺序考虑人们。

最新更新