优化算法的技巧
Posted
技术标签:
【中文标题】优化算法的技巧【英文标题】:Tips in optimizing an algorithm 【发布时间】:2014-04-01 03:29:12 【问题描述】:我会尽量用措辞来表达这个问题,但不要让它听起来像是在寻找家庭作业的答案(这只是算法的练习题)
您有一个数字数组,其中每个值最多出现 2x [1 3 5 2 5 1 2 3] 检查从一个值到另一个自身实例的总和 (5 + 2 + 5) (2 + 5 + 1 + 2)
找到一个算法,找到这个总和的最大值。
我想出了一个非常简单的算法:
iterate through the array (for i=1 to n)
iterate through the remaining array (for j=i+1)
if A[i] == A[j]
s = 0
iterate through the values between those two points (for k=i to j)
s = s + A[k]
maxVal = max(maxVal,s)
我可以采取哪些步骤来优化算法。 (或与此相关的任何算法)。显然,这个解决方案是第一个想到的,但我无法想象出更有效的更好解决方案。
编辑:为了这个问题,我只想说所有元素都是积极的
【问题讨论】:
【参考方案1】:计算累积和数组:
C[0] = A[0]
for i = 1 to n
C[i] = C[i - 1] + A[i]
A[1 3 5 2 5 1 2 3]
C[0 1 4 9 11 16 17 19 22]
找到配对时使用这些值:
Sum(i to j) = C[j] - C[i - 1]
P.S.所有的元素总是积极的吗?
【讨论】:
哇,这真是太聪明了!我真的希望我有这样的创造性解决方案的诀窍。在尝试优化我的解决方案时,您首先考虑的是什么? (试图提高我的优化技能) 如果您可以使用额外的内存,请查看 Pham Trung 关于 hashmap/dusctionary 的建议 @CoderNinja 从中缀聚合减少到前缀聚合是算法工程中众所周知的构造。学习这些东西只需要一点练习。如果您想练习算法/解决问题的技能,我可以推荐 TopCoder 或 Codeforces 等平台(但这需要付出努力,没有免费的午餐,也没有简单的技巧可以神奇地让您更快地解决问题)。 @CoderNinja 您可能会注意到,初始算法一次又一次地计算几乎相似的总和(在稍微偏移的间隔上)。【参考方案2】:您可以通过预先计算从索引 1 到索引 i 的所有总和并将其存储到数组中来摆脱最内层循环,调用 sum
。所以如果你想得到 i 和 j 的和,结果会是 sum[j] - sum[i - 1]。
for(i = 1 to n)
sum[i] = A[i];
if(i - 1 > 1)
sum[i] += sum[i - 1];
还要注意数组中的每个值只有两次出现,我们可以使用映射/字典或数组pos
(如果可能的话)记住这个值的第一个位置,如果我们再次看到它,我们可以用它来计算第一个和这个位置的和。
pos[];
for(i = 1 to n)
if(pos[A[i]] ==0)
pos[A[i]] = i;
else
result = max(result,sum[i] - sum[pos[A[i]] - 1])
所以总的来说,这个的时间复杂度是 O(n)
【讨论】:
预期 O(n) ;) 甚至可能是 O(n) 的概率很高,具体取决于哈希表的实现以上是关于优化算法的技巧的主要内容,如果未能解决你的问题,请参考以下文章