如何降低装桶程序的时间复杂度?
Posted
技术标签:
【中文标题】如何降低装桶程序的时间复杂度?【英文标题】:How to reduce the time complexity of bucket filling program? 【发布时间】:2015-10-27 05:32:15 【问题描述】:我正在解决一个问题,如下所示:
连续有 n 个桶。园丁给水桶浇水。每天,他都会在 i 和 j (含)位置之间给水桶浇水。他为不同的 i 和 j 这样做了 t 天。
输出桶中水的体积,假设初始体积为零,每次浇水将体积增加1
。
输入:第一行包含 t 和 n,以空格分隔。 接下来的 t 行包含由空格分隔的 i 和 j。
输出:单行显示 n 个存储桶中的体积,以空格分隔。
示例:
输入:
2 2 1 1 1 2
输出:
2 1
约束:
0 4; 1 5
我试过这个问题。但我使用 O(n*t) 算法。我每次将桶从 i 增加到 j 在每一步。但这显示了时间限制错误。有没有有效的算法来解决这个问题。一个小提示就足够了。
P.S:我使用 C++ 和 Java 作为标签,因为程序可以用这两种语言编写。
【问题讨论】:
解析用户输入并打印输出可能会比您的计算花费更多的时间...... 不,最多只有11行输入...请检查问题 啊,我明白了。 10⁵ 是问题所在。 等等,什么?现在 t≤10⁴。这与 t完全不同 @DaoWen 实际上我编辑了问题..运行时间是 n*t..抱歉,感谢您帮助我解决这个问题.. 【参考方案1】:记住每个桶和前一个桶的区别,而不是记住每个桶里的水量。
【讨论】:
那么在每一步我们都必须增加 d[i] 和 d[j+1],其中 d 是差值数组。这是正确的吗? 如何知道每个桶的水量? @Bhushi maked[i] + 1
和 d[j+1]-1
【参考方案2】:
有两个区间列表,一个按上限排序,一个按下限排序
然后从体积 v 为 0 开始迭代 n。
On each iteration over n
check if the next interval starts at n
if so increase v by one and check the next interval.
do the same for the upper bounds but decrease the volume
print v
repeat with the next n
【讨论】:
【参考方案3】:我认为这里的关键观察是您需要找到一种方法来表示您的(可能)105 个存储桶,而无需为每个存储桶实际分配空间,并单独跟踪它们.您需要提出一个稀疏表示来跟踪您的水桶和里面的水。
您的输入来自范围这一事实为您提供了一个很好的提示:您可能应该在稀疏表示中使用范围。您可以通过跟踪每个范围末端的存储桶来做到这一点。
我建议您使用链接列表来执行此操作。每个列表节点将包含 2 条信息:
-
一个桶号
那个桶里的水量
您假设当前水桶和下一个水桶之间的所有水桶的水量相同。
这是一个例子:
Input:
5 30
1 5
4 20
7 13
25 30
19 27
这是算法的每一步会发生的情况,步骤 1 是初始状态,每个连续的步骤是你在解析一行后所做的。
-
1:0→
NULL
(所有bucket都是0)
1:1→6:0→NULL
(1-5有1,其余为0)
1:1→4:2→6:1→21:0→NULL
(1- 3个有1个,4-5个有2个,6-20个有1个,其余的有0个)
1:1→4:2→6:1→7:2→14:1 →21:0→NULL
1:1→4:2→6:1→7:2→14:1 →21:0→25:1→NULL
1:1→4:2→6:1→7:2→14:1 →19:2→21:1→25:2→28:1→@ 987654327@
你应该可以从上面的例子中推断出这个方法的复杂度实际上是O(t2)而不是O(n×t ),所以这应该快得多。正如我在上面的评论中所说,这种方式的瓶颈实际上应该是解析和输出,而不是实际的计算。
【讨论】:
问题原来说t≤10。现在改成 t≤10⁴,我觉得稀疏表示已经没有意义了。【参考方案4】:这是一个空间和时间复杂度为O(n)的算法
我用java,因为我习惯了
1) 创建一个包含 n 个元素的哈希集 2)每次浇水时都会增加相应的元素计数 3) 文件解析完成后,遍历hashset计算结果。
【讨论】:
以上是关于如何降低装桶程序的时间复杂度?的主要内容,如果未能解决你的问题,请参考以下文章