Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 面试中的动态规划算法_Algorithm_Dynamic Programming - Fatal编程技术网

Algorithm 面试中的动态规划算法

Algorithm 面试中的动态规划算法,algorithm,dynamic-programming,Algorithm,Dynamic Programming,这个问题是在一次采访中问我的,它尴尬地暴露了我在动态规划方面的缺点。如果有人能帮我破解这个,我将不胜感激。此外,如果你能在设计解决方案的过程中解释你的思维过程,这将对我(和其他人)非常有帮助,因为当我看到一个使用动态编程范式但很难想出自己的解决方案时,我似乎能够理解 没有进一步的麻烦,这里是我被问到的问题 给定一个整数i并设置X的k点x1,x2xk在实线上,使用动态规划从集合X中选择i点,以最小化从X中的每个点到i中的点的距离之和 对于大多数DP问题,我试图找到一种归约-征服关系。也就是说,我可

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

没有进一步的麻烦,这里是我被问到的问题


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

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

一些表示法:假设X={x1,x2,…,xk},并表示缩减集Xn={Xn,Xn+1,…,xk}

因此,观察结果是x1要么是
i
点之一,要么不是。让我们调用
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
的集合(对于
i=0
的情况是如此,根据我们上面对MSD的定义,归纳法是正确的)

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

这给我们留下了一个O((ik)2)的运行时

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

我想是后者

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

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

=O(k2*ilogi)

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


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

你知道,除非这份工作是专门针对运筹学的工作,否则我觉得这是一个不合格的面试问题。也就是说,你应该温和但坚定地与面试官握手,向他们表示感谢,并解释说在面试中使用这种愚蠢的问题证明他们不是你希望被雇用的地方。我们是否将I中的点从X中删除?因为如果没有,我不确定我是否看到了问题的一点。@IgnacioVazquez Abrams这没关系,因为我没有,那么总数将是0。问题的关键是选择一个具有固定大小的子集,使得从X中的每个点到集合的距离之和最小,并且您以类似于背包的方式来处理它。这里有一个提示。尝试解决这个相关的,但稍微容易看到的问题。给定一个整数i和实线上k个点的集合X,从集合X中选择i个点,以使从X中的每个点到i中的一个点的正确距离最小化。如果b>a,则右距离(a,b)=b-a,否则它是无穷大。这听起来像是谷歌在工作中提出的问题,实际上主要涉及将web元素向左或向右移动几个像素。查理说得对。嗨,谢谢你的回复。你能解释一下你是如何推导出MSD(i,Xk)=MSD(i-1,Xk-1)U{x1}或MSD(i,Xk-1)的吗?关于@user976078,这确实是关键的观察结果。嗯,你要找的那一套是很明确的。它可能不是唯一的,尽管至少有一个这样的集合