微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

找到绳子的最小长度

如何解决找到绳子的最小长度

我有以下编程问题:

给出一个整数长度的数组作为输入,每个元素表示所需的绳索的长度,找到原始绳索的最小长度,因为在每一步中,您只能将绳索的一半长度和每个绳索的长度绳子必须是整数。如果不存在这样的绳索,则输出-1。

有关将长度x的绳索“减半”的其他信息:

  • 如果x可被2整除,则两条所得的绳索的长度将为x / 2
  • 否则,两条所得的绳索的长度将分别为地板(x / 2)和天花板(x / 2)

例如,如果我需要[3,5,2],那么我需要的最小尺寸为10,因为'10'可以分为2'5',其余的'5'可以分为'3'和'2'。然后,我将得到准确的结果[3,5,2]。最终也可以允许多余的绳索。

我提供了一个功能,该功能可以确定特定长度的绳索是否可以拆分为所需的长度。

我最初是想在搜索空间中进行某种二进制搜索[所需的最大绳索长度,___],但我不确定应该设置的上限。另外,我意识到这不一定奏效,因为更长的绳索不一定能保证绳索可以分成所需的长度。

现在,我唯一的解决方案是线性搜索,但这似乎太慢了,我不确定是否会导致没有有效绳索的情况。

非常感谢任何指导!

解决方法

考虑任何所需的段长度m,并假设我们想通过将绳索精确地k减半来获得此段。然后,我们将考虑的最短绳索的长度为(2^k)*m - 2^k + 1。如果我们将这条绳子切成k的一半,并在每一步中丢弃较短的那一半,那么我们最终会得到一段长度为m的片段。我们将考虑的最长绳索的长度为(2^k)*m + 2^k - 1。如果我们将这条绳子切成k的一半,并在每一步中丢弃较长的那一半,那么我们最终还会得到一段长度为m的片段。

对于我们的长度m段,对于某些正整数[(2^k)*m - 2^k + 1,(2^k)*m + 2^k - 1],我们只需要考虑长度在k区间内的绳索。在合理的假设下,最终的绳索长度可以用64位无符号整数表示,k最多为64。因此,使用上面的间隔符号,只有64个间隔包含所有可能的绳索长度,用于获取长度为m的分段。

现在这是有趣的部分:可以说,n个必需的长度m_1,m_2,...,m_n段。对于任何分段m_i,我们将第k个候选间隔正式定义为:

I(m_i,k) = [(2^k)*m_i - 2^k + 1,(2^k)*m_i + 2^k - 1]

对于任何分段m_i,让X(m_i)表示64个候选间隔I(m_i,1),I(m_i,2),64)的并集。我们知道解决方案绳索的长度x必须包含在每个nX(m_1),X(m_2),X(m_n)中。因此,我们缩小了搜索所有X(m_i)的交集的搜索空间。

通过首先生成64 * n间隔I(m_i,k),可以有效地遍历搜索空间中的所有值,每个间隔由您喜欢的编程语言中的一对整数表示(小心溢出!)。然后,您可以使用快速整数排序器按它们的第一部分(即它们的左间隔边界)对这些对进行排序。基数排序。最后,在搜索空间中进行迭代仅需要对排序的间隔进行从左到右的仔细扫描,始终检查所需的交集(我故意在此省略一些技术细节)。

例如,使用最短绳索[7,7,8,14]的必需段57

I(7,1) = [13,15]
I(7,2) = [25,31]
I(7,3) = [49,63]
I(7,4) = [97,127]
...

I(8,1) = [15,17]
I(8,2) = [29,35]
I(8,3) = [57,71]
I(8,4) = [113,143]
...

I(14,1) = [27,29]
I(14,2) = [53,59]
I(14,3) = [105,119]
...

Search Space: [29,29],[57,59],[113,119],...

如您所见,搜索空间已经大大缩小,因此解决方案实际上是搜索空间的第二个最小元素!

希望这会有所帮助;)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。