难以思考分而治之的方法
Posted
技术标签:
【中文标题】难以思考分而治之的方法【英文标题】:Difficulty in thinking a divide and conquer approach 【发布时间】:2021-09-14 17:02:38 【问题描述】:我是自学算法。众所周知,分而治之是算法设计范式之一。我研究了mergeSort、QuickSort、Karatsuba Multiplication,将数组的反转计数作为这种特定设计模式的示例。虽然听起来很简单,将问题划分为子问题,递归地解决每个子问题,并合并每个子问题的结果,但我发现很难形成如何将这种逻辑应用于新问题的想法。据我了解,所有上述规范示例都提出了一个非常聪明的技巧来解决问题。例如,我正在尝试解决以下问题:
给定一个由 n 个数字组成的序列,使得两个连续数字之间的差是恒定的,以对数时间找出缺失的项。
Example: [5, 7, 9, 11, 15]
Answer: 13
首先,我想到了可以使用分而治之的方法来解决它的想法,因为天真的方法需要 O(n) 时间。根据我对分而治之的理解,我是这样处理的: 原问题可以分为两个独立的子问题。我可以递归地搜索两个子问题中的缺失项。所以,我先分问题。
leftArray = [5,7,9]
rightArray = [11, 15]
现在它说,我需要递归地解决子问题,直到它变得微不足道。在这种情况下,子问题的大小变为 1。如果只有一个元素,则缺少 0 个元素。现在合并结果。但我不知道该怎么做或它会如何解决我原来的问题。
当然,我在这里遗漏了一些重要的东西。我的问题是如何解决这种分而治之的问题。我应该想出一个像 mergeSort 或 QuickSort 这样的技巧吗?我越是看到这类问题的解决方案,感觉我是在记住解决方法,而不是理解,每个问题的解决方法都不一样。任何关于解决分而治之的心态的帮助或建议将不胜感激。我已经尝试了很长时间来发展我的算法技能,但我几乎没有进步。提前致谢。
【问题讨论】:
【参考方案1】:你有正确的方法。唯一缺少的部分是一种 O(1) 的方式来决定要丢弃哪一边。
首先,注意你的问题中的数字必须是有序的,否则你不能做得比 O(n) 更好。还需要至少三个数字,否则你不会弄清楚“步骤”。
有了这种理解,您可以通过检查前三个项来确定 O(1) 时间内的“步长”,并查看连续项之间的区别。有两种可能的结果:
两者的区别是相同的,并且 一个差异是另一个差异的两倍。案例 2 很幸运地为您提供了一个解决方案,因此从现在开始我们将只考虑第一个案例。有了步骤,您可以通过减去端点并将结果与间隔数乘以步骤进行比较来确定范围中是否存在间隙。如果您得出相同的结果,则该范围没有缺失项,并且可以丢弃。当两半都可以丢弃时,间隙就在它们之间。
【讨论】:
关于订购的要点 - 没有一些已知的订单,有必要全部检查一下 非常感谢@Sergey Kalinichenko。我正在尝试了解您提供的方法。那么,这是否发生在解决方案的分而治之或合并步骤中?我的意思是在快速排序中,我们在除法步骤中完成主要工作,然后递归,在合并排序中,它发生在递归之后的合并步骤中。抱歉,我可能听起来很愚蠢,但我正在尝试建立一个心理模型来解决这些类型的问题。 @AshequlHaque 由于解决方案是 O(log n),因此没有“工作”需要完成各个部分。这就是这个问题与 mergeSort 不同的原因。你需要做的就是分裂,因为“征服”是自动发生的,而且是免费的。这将类似于二分搜索算法,它不断划分区间直到找到解决方案,因为划分区间是“有效负载”工作。 再次感谢先生。 @SergeyKalinichenko 如果你有时间,最后一个问题。当您看到这些类型的问题时,首先想到要解决的问题是什么? @MarkRansom 这将扼杀 O(log N) 要求。【参考方案2】:正如 @Sergey Kalinichenko 指出的那样,这假设传入的集合是有序的
但是,如果您确定输入是有序的(在这种情况下很可能),请观察第 n 个位置的值是 start + jumpsize * index
;这使您可以平分以找到它移动的位置
示例:[5, 7, 9, 11, 15] 答案:13
start = 5
jumpsize = 2
检查中点:5 * 2 * 2 -> 9
这是有效的,因此移位必须在 中点之后
递归
您可以通过检查前 3 个值来找到 jumpsize
a, b, c = (language-dependent retrieval)
gap1 = b - a
gap2 = c - b
if gap1 != gap2:
if (value at 4th index) - c == gap1:
missing value is b + gap1 # 2nd gap doesn't match
else:
missing value is a + gap2 # 1st gap doesn't match
bisect remaining values
【讨论】:
该问题并未指明jumpsize
是已知的。
确实如此;但是,您可以通过检查前 3 个值来了解它(如果它们不平衡,则检查第 4 个值的确切位置)
谢谢@ti7,您能大致了解一下您是如何处理它的吗?我应该想出一个公式并递归应用它吗?
@MarkRansom 我添加了一个关于如何检测大小的代码示例!
@AshequlHaque 是的,您知道结果在哪一半,只要您发现不匹配,您只需要新中点的索引和大小就知道它是previous value + size
以上是关于难以思考分而治之的方法的主要内容,如果未能解决你的问题,请参考以下文章
Elastic Search | 记一次Kibana执行ES-DSL脚本实战思考过程
Elastic Search | 记一次Kibana执行ES-DSL脚本实战思考过程