如何降低装桶程序的时间复杂度?

Posted

技术标签:

【中文标题】如何降低装桶程序的时间复杂度?【英文标题】:How to reduce the time complexity of bucket filling program? 【发布时间】:2015-10-27 05:32:15 【问题描述】:

我正在解决一个问题,如下所示:

连续有 n 个桶。园丁给水桶浇水。每天,他都会在 ij (含)位置之间给水桶浇水。他为不同的 ij 这样做了 t 天。

输出桶中水的体积,假设初始体积为零,每次浇水将体积增加1

输入:第一行包含 tn,以空格分隔。 接下来的 t 行包含由空格分隔的 ij

输出:单行显示 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 make d[i] + 1d[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:0NULL(所有bucket都是0) 1:16:0NULL(1-5有1,其余为0) 1:14:26:121:0NULL(1- 3个有1个,4-5个有2个,6-20个有1个,其余的有0个) 1:14:26:17:214:1 21:0NULL 1:14:26:17:214:1 21:025:1NULL 1:14:26:17:214:1 19:221:125:228:1→@ 987654327@

你应该可以从上面的例子中推断出这个方法的复杂度实际上是O(t2)而不是O(n×t ),所以这应该快得多。正如我在上面的评论中所说,这种方式的瓶颈实际上应该是解析和输出,而不是实际的计算。

【讨论】:

问题原来说t≤10。现在改成 t≤10⁴,我觉得稀疏表示已经没有意义了。【参考方案4】:

这是一个空间和时间复杂度为O(n)的算法

我用java,因为我习惯了

1) 创建一个包含 n 个元素的哈希集 2)每次浇水时都会增加相应的元素计数 3) 文件解析完成后,遍历hashset计算结果。

【讨论】:

以上是关于如何降低装桶程序的时间复杂度?的主要内容,如果未能解决你的问题,请参考以下文章

程序优化--降低复杂度

程序优化--降低复杂度

如何降低排序的时间复杂度?

如何降低这个问题的时间复杂度

如何降低以下代码块的时间复杂度?

重构此方法以将其认知复杂度从 16 降低到允许的 15。如何重构和降低复杂度?