【问题标题】:dynamic programming algorithm during an interview [closed]面试中的动态规划算法[关闭]
【发布时间】:2011-11-29 16:17:06
【问题描述】:

这个问题是在一次采访中问我的,很尴尬地暴露了我在动态规划方面的不足。如果有人能帮我破解这个,我将不胜感激。此外,如果您可以在设计解决方案的过程中解释您的思维过程,这对我(和其他人)将非常有帮助,因为当我看到使用动态编程范式但难以实现的解决方案时,我似乎能够理解和我自己的一样。

事不宜迟,下面是我被问到的问题。

给定一个整数i,并在实线上设置kx1x2,...xk中的X,从集合X中选择i点,以便使用动态规划最小化从X 中的每个点到i 中的点的距离总和。

【问题讨论】:

  • 你知道,除非这份工作是专门针对运筹学工作的,否则我觉得这是一个不合格的面试问题。也就是说,应该轻轻而坚定地握住面试官的手,感谢他们,并解释说,在面试中使用这种愚蠢的问题证明他们不是一个应该被雇用的地方。
  • 我们是否从 X 中删除了 I 中的点?因为如果没有,我不确定我是否看到了问题的重点。
  • @IgnacioVazquez-Abrams 没关系,因为我没有,那么总和将为 0。问题的关键是选择一个具有固定大小的子集,以便每个子集的距离总和X 中指向集合的点是最小的,并且您以类似于背包的方式接近它
  • 这里有一个提示。尝试解决这个相关但更容易看到的问题。给定一个整数 i 和实线上有 k 个点的集合 X,从集合 X 中选择 I 个点,以使 X 中的每个点到 I 中的点的右距离最小。正确的距离(a, b) = b - a if b > a,否则为无穷大。
  • 这听起来像是谷歌要求的工作,实际上主要涉及将网络元素向左或向右移动几个像素。查理是对的。

标签: algorithm dynamic-programming


【解决方案1】:

对于大多数 DP 问题,我尝试找到一种归约与征服的关系。也就是说,我可以通过每一步减少问题大小的关系(如分而治之,但通常不会划分问题,它只是删除一小部分)。在这个问题中(像许多其他问题一样),我们可以做一个非常简单的观察:第一个点要么在i 点的集合中,要么不在。

一些符号:假设 X = {x1, x2, ..., xk},并表示约简设置 Xn = {xn, xn+1, ..., xk}。

所以观察结果是 x1i 点之一,或者不是。让我们调用我们的i-set 查找函数 MSD(i,Xk)(最小距离总和)。我们可以如下表达该切面观察:

MSD(i,Xk) = MSD(i-1,Xk-1) U {x1 } 或 MSD(i,Xk-1)

我们可以通过实现一种检查这两个选项中的哪一个的简单方法来形式化“非此即彼”部分:我们遍历集合 X 并计算距离之和,然后检查哪个实际上更小。此时我们注意到,该检查的运行时间为ki,因为我们将天真地遍历每个k 点并获取与i 大小集合中的点的最小距离。

我们对基本情况做了两个简单的观察:

MSD(i,Xi) = Xi
MSD(0,Xn) = {}

首先,当在一组大小为i 中寻找i 点时,我们显然只取整个集合。
第二个是当在集合中没有点时,我们返回空集合。这以归纳方式确保 MSD 返回大小为 i 的集合(根据我们上面对 MSD 的定义,i=0 和归纳为 true 的情况是正确的)。

就是这样。这将找到合适的集合。 运行时复杂度的上限是 O(ik * step),其中 step 是我们从上面检查的 O(ik)。这是因为 MSD 将在 0-i 和 X1 - Xk 范围内的参数上运行,这是 ik 可能的参数的总数。

这让我们的运行时间为 O((ik)2)。

以下部分是基于我对 OP 问题的理解。我不确定 X 中每个点与 i 大小子集的距离是否是子集中每个点与 每个其他点 的距离之和,或者是距离之和X 中的每个点来自子集本身
IE。 X 中 x 的 sigma(x 到子集中每个点的距离总和)或 X 中 x 的 sigma(x 到子集的距离,即从 x 到子集中任何点的最小距离)

我假设是后者。

我们可以通过优化上面的O(ik) 检查来减少运行时间。我们注意到元素实际上是排序的(尽管在当前符号中以相反的顺序),因为当我们添加它们时,我们总是从右侧进行。假设它们一开始就被分类,它们将一旦脱离 MSD 例程。如果一开始没有对它们进行排序,我们可以对它们进行排序,无论如何这只会花费O(klogk)

排序后,检查每个点与集合中一个点的距离将为k * logi,因为我们对每个点进行二分搜索。这会产生O(ik * klogi + klogk)
的总运行时间 = O(k2 * ilogi).

最后,我们可以将其表示为 O(k3logk)。不是最快的解决方案,而是一个解决方案。

我确信还有更多优化,但这是我的 2c。

【讨论】:

  • 您好,感谢您的回复。您能否解释一下您是如何推导出 MSD(i,Xk) = MSD(i-1,Xk-1) U {x1} 或 MSD(i,Xk-1) 的?问候,
  • @user976078,这确实是关键的观察结果。好吧,您正在寻找的集合是明确定义的。尽管肯定存在至少一个这样的集合,但它可能不是唯一的(证明:大小为 i 的 X 的子集数量有限,因此定义明确的属性保证至少有一个最小值)。如果是这样,我可以问自己一个问题:x1(X 中的第一个元素)是否在这些最小集合中?一开始我没有办法知道。但我知道它要么是,要么不是。对吗?
  • 所以现在,我不必解决寻找 X 的最小 i 大小子集的更大问题,而是足以解决稍微小一点的问题:我希望能够找到 MSD (i-1,Xk-1) 它是 Xk-1 的 i-1 大小的子集,它是比 X 更小的集合。如果我假设 x1 is 在这些最小集合之一中,这很有用.虽然就像我们说的,但也许不是。所以我还希望能够解决 MSD(i,Xk-1),它是 Xk-1 的 i 大小的子集,也是一个稍微小一点的问题。如果 x1 在这些最小集合之一中,此解决方案将很有用。
  • 如果我能解决这两个较小的问题(子问题),确定两者中哪个确实较小,那么我一定找到了答案。回顾一下,我们说 x1 在我们正在寻找的集合中,或者不在。因此,如果我可以解决子问题并检查哪个更优化,我可以回答 x1 是否存在的问题。这导致了递归关系。
  • 非常感谢您到目前为止的帮助。我有最后一个跟进问题。在您对 MSD 的定义中,您定义的 Xk 到底是什么?每次迭代它如何变化?您是否从所有 X 点开始并在每次迭代中逐渐将集合缩短一个?其次,你怎么知道这个算法会给出从 X 中的每个点到集合的最小距离总和?如果我们计算最大和,我们可以做几乎同样的事情。对吗?
猜你喜欢
  • 1970-01-01
  • 2013-04-25
  • 2011-10-07
  • 2012-03-26
  • 2013-11-27
  • 1970-01-01
相关资源
最近更新 更多