我试图通过解决协同性问题来提高我的技能。我找到了这个:https://codility.com/programmers/lessons/9-maximum_slice_problem/max_double_slice_sum/
我实际上从理论上理解了解决方案:
- 对数组使用Kadane算法,并在每个索引处存储总和
- 反转数组并执行相同操作
- 通过一次循环一个结果集,找到两者之和为最大的点
- 最大值是最大双切片
我的问题与其说是关于如何解决这个问题。我的问题是,人们如何想象这将是解决这个问题的方法。至少有3个不同的概念需要使用:
-
如果数组中的所有元素都是正的或负的,则与数组中有一些正元素和负元素时的情况不同。
-
Kadane算法
-
向前和反向越过阵列。
尽管如此,Codality还是将这个问题标记为"无痛"。
我的问题是我错过了什么吗?我似乎很难在不了解这些概念的情况下解决这个问题。
有没有一种技术可以让我从零开始,从非常基本的概念开始,逐步达到解决这个问题所需的概念。还是说,在开始问题之前,我就应该知道这些概念?
当我不知道未来需要的概念时,我该如何为自己解决这些问题做好准备?
我认为你想得太多了,这就是为什么你发现它比实际更困难的原因:
如果数组中的所有元素都是正的或负的,则与数组中有一些正元素和负元素时的情况不同。
这不一定是另一种情况。你也许可以想出一种算法,它不在乎这种区别,而且无论如何都能工作。
你不需要从理解这种区别开始,所以在必要的时候不要去想它
Kadane算法
不要想算法,要想问题需要什么。通常,10多段的问题陈述可以用更少的语言表达。
让我们看看如何简化问题陈述。
它首先将切片定义为三元组(x, y, z)
。它定义为从x+1
开始、到z-1
结束且不包含y
的元素的总和。
然后它要求最大和片。如果我们需要最大切片,那么我们在定义中需要x
和z
吗?我们不妨让它在任何地方开始和结束,只要它能给我们最大的总和,不是吗?
因此,将切片重新定义为数组的子集,该子集从任何地方开始,一直到某个y-1
,从y+1
开始,在任何地方结束。简单多了,不是吗?
现在你需要这样的最大切片。
现在您可能认为,对于每个y
,您需要从y+1
开始的最大和子数组和从y-1
结束的最大和个子数组。如果你能找到这些,你可以为每个y
更新一个全局最大值。
你是怎么做到的?这应该会让你看到Kadane的算法,它完成了你想要的一半:它计算以某个x
结尾的最大和子数组。因此,如果你从两侧计算,对于每个y
,你只需要找到:
kadane(y - 1) + kadane_reverse(y + 1)
并与全球最大进行比较
阴性和阳性没有特殊情况。不要一看到问题就想着"卡丹的!"。
其想法是在不改变其含义的情况下尽可能简化需求。然后你用你的算法和演绎技巧来达成一个解决方案。这些技能是经过时间和经验磨练的。