有一个数组包含一个0到999之间的数字,严格按顺序增加。
例如
int[] array = {0, 24, 55, 124, 200, 259, 400, 503, 666, 797};
我要做的是实现一个选择N个数字的函数,以便最大化这些选中数字之间的距离的最小值。
例如,如果N是3,则拾取的数字是0,400,797,间隔是400和397;所以返回值是397(应该最大化)。如果我们选择其他数字集,则返回值将小于(或等于)397。
我想使用递归来实现它,但我很难对它进行编码。你想帮助我吗?
答案 0 :(得分:2)
使用dynamic programing可以解决此问题。
如果我们在选择s[c][p]
数字时将c
定义为解决方案,并且最后选择的数字在输入数组中具有索引p
。
然后,我们可以将s[c][p]
计算为max for i=0..p of max(s[c-1][p-i], array[p] - array[p-i])
在以下状态开头:s[1][0..n]
,其中n
是输入数组的长度,应该具有值0
。
拥有s[1][0..n]
我们现在可以使用给定的公式轻松计算s[2][0..n]
有s[2][0..n]
我们现在可以轻松计算s[3][0..n]
等等...
整个问题的解决方案是max s[N][N-1..n]
,其中n
是输入数组的长度,N
是要选择的数字的数量。
此解决方案的时间复杂度为O(N*n^2)
说明:我们计算s[0..N][0..n]
的值,其中每个计算的时间复杂度为O(n)
。
此解决方案的内存复杂性为O(n)
说明:要计算s[c][0..n]
,您只需要s[c-1][0..n]
,因此在每个时间点实际只需要2*n
个内存。
编辑:您可以使用递归来实现所描述的算法,使用称为memoization(https://en.wikipedia.org/wiki/Memoization)的编程技术。