【问题标题】:What is the time and space complexity of this algorithm?这个算法的时间和空间复杂度是多少?
【发布时间】:2020-05-03 19:40:24
【问题描述】:

这个算法的时间和空间复杂度是多少?

我计算WC时间复杂度如下:

  1. 所有启动都是 O(1) 次

  2. for 循环为 O(n),因为

    • 外部 for 循环最多运行 n 次,
    • 每次启动费用为 1,
    • 内部 for 循环最多运行 17 次,并且
    • if 语句和分配的成本分别为 1。
    • 我计算 O((n+1+1)*(17+1+1+1+1+1+1+1+1+1+1+1+1) 然后忽略常数 O(n) .
  3. 算法第二部分的时间复杂度如下:

    • 启动列表的成本为 1
    • for 循环为 17
    • 召开会议的费用为 1
    • if 语句的成本为 1
    • indexOfEndTime 初始化为 1
    • for 循环为 16
    • if 语句为 1
    • 分配为 1 个
    • O(1+(17+1+1+1+1+1+1)*(16+1+1+1+1)+1) 这只是常数值,比如 c。
  4. T(n) = Step 1 + Step 2 + Step 3 = O(1+n+c) 这意味着我最坏情况的时间复杂度是 O(n)。

这是正确的吗?您能否确认我的每个计算是否正确?在这种情况下,最佳情况的时间复杂度将是 O(1)?考虑平均情况是否有意义?如果可以,如何解决?

最后,我计算出最佳/平均/最差空间复杂度为 O(n)。

    public static List<Meeting> mergeRanges(List<Meeting> meetings) {
        byte available = 0;
        byte reservedBlockStart = 1;
        byte reservedBlockMiddle = 2;
        byte reservedBlockEnd = 3;
        byte[] slots = new byte[17];

        for(Meeting meeting : meetings) {
            byte startTime = (byte) meeting.getStartTime();
            byte endTime = (byte) meeting.getEndTime();
            for(byte i = startTime; i <= endTime; i++) {
                if(slots[i] == available) {
                    if(i == startTime) {
                        slots[i] = reservedBlockStart;
                    } else if(i == endTime) {
                        slots[i] = reservedBlockEnd;
                    } else {
                        slots[i] = reservedBlockMiddle;
                    }
                } else if(slots[i] == reservedBlockStart) {
                    if(i != startTime) {
                        slots[i] = reservedBlockMiddle;
                    }
                } else if(slots[i] == reservedBlockEnd) {
                    if(i != endTime) {
                        slots[i] = reservedBlockMiddle;
                    }
                }
            }
        }

        List<Meeting> condRange = new ArrayList<Meeting>();
        for(byte i = 0; i < slots.length; i++) {
            Meeting meet = new Meeting(0,0);
            if(slots[i] == reservedBlockStart) {
                byte indexOfEndTime = i;
                meet.setStartTime(i);
                for(byte j = (byte)(i + 1); j < slots.length; j++) {
                    if(slots[j] == reservedBlockEnd) {
                        meet.setEndTime(j);
                        indexOfEndTime = j;
                        j = (byte)(slots.length - 2);
                    } 
                }
                condRange.add(meet);
                i = (byte)(indexOfEndTime - 1);
            }
        }
        return condRange;
    }

【问题讨论】:

  • 我只想说它是 O(n*17) = O(n)。因为第一个循环超过 n,然后第二个循环超过 17 个元素,你说它是恒定的。你经历了这两次,但 O(2*n) 与 O(n) 相同...
  • > 考虑平均情况是否有意义,如果确实如此,如何解决? “平均情况”运行时要求您了解/定义您期望看到的输入分布(我相信,作为n 的函数)。然后,您可以在给定 n 的情况下获取输入分布的平均运行时间。
  • @KevinWang 在这种情况下,我们可以说最好和最坏的情况都是 O(n),所以平均情况一定是 O(n) 也一样,无论分布是平均的。

标签: java algorithm performance big-o


【解决方案1】:

您的最坏情况分析似乎完全正确;我没有注意到其中有任何错误,并且得到了相同的结果。

您的最佳案例分析不正确;你说在最好的情况下它需要 O(1) 时间,但是你在 meetings 列表上的循环总是完成 n 次迭代,所以这种情况也需要 O(n ) 时间。您可能错误地假设列表长度为 1,在最好的情况下甚至为 0;这不算作“案例”,因为您需要考虑由大小 n 参数化的一系列输入,以便渐近分析完全有意义。

您的空间复杂度分析也不正确。您的算法创建了两个数据结构:slots 数组具有恒定大小,condRange 列表也恰好具有恒定大小,因为它仅附加到第三个循环,我们已经建立了 O(1)操作,因此该列表的add 操作数也是 O(1)。即使此列表的最终大小为 O(n),它也是算法的输出,因此 任何 正确的算法都必须创建该大小的列表;通常测量“辅助”空间复杂度会更有用,即临时数据结构使用的空间,这些数据结构仅存在于算法的内部工作。

有一个假设需要明确说明,即会议startTimeendTime 始终在 0 到 16(含)范围内,因此将其用作索引是有意义的在slots。顺便说一句,你不需要为常量c 命名,你可以在那里写 O(1)。

【讨论】:

  • 感谢您的解释!是的,如果列表长度在最佳情况下为 1 或 0,我确实错误地考虑了这种情况。你的空间复杂度解释也很清楚。感谢您的意见!
猜你喜欢
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
相关资源
最近更新 更多