【问题标题】:Big O of Ugly Numbers Algorithm (Brute force method)丑数大 O 算法(蛮力法)
【发布时间】:2023-06-13 16:02:01
【问题描述】:

问题链接:Ugly Numbers

你如何找到丑数的蛮力(简单方法)解决方案的大 O。

我看到这部分代码:

    /* Function to check if a number is ugly or not */
int isUgly(int no) 
{ 
  no = maxDivide(no, 2); 
  no = maxDivide(no, 3); 
  no = maxDivide(no, 5); 

  return (no == 1)? 1 : 0; 
}     

每个步骤都需要log_2(x) + log_3(x) + log_5(x) 步骤,其中x = no

所以这意味着运行时间是 (log_2(x) + log_3(x) + log_5(x))n 其中 x 是输出的结果。但是,算法的结果不能是大 O 符号的一部分,对吧?如果不能,这将减少到 cn 对吗? c > 结果。什么是正确的证明方法?

【问题讨论】:

    标签: algorithm big-o proof


    【解决方案1】:

    丑数也称为正数。可以看到from the Wikipedia article,可知到m的正则数个数是

    (ln(m*sqrt(30))^3 / (6*ln(2)*ln(3)*ln(5)) + O(ln(m))
    

    换句话说,您的getNthUglyNo 将调用isUgly 以获取n-th 常规号码

    ~ 1/sqrt(30) * exp((n*6*ln(2)*ln(3)*ln(5))^(1/3))
    

    次。

    0M 之间的均匀随机整数x2^y 整除的概率是渐近的1/2^y,因此调用maxDivide(no, 2); 中的循环迭代的平均次数是O(1),等效于maxDivide(no, 3);maxDivide(no, 5);

    因此你的算法是

    Theta( exp((n*6*ln(2)*ln(3)*ln(5))^(1/3)) )
    

    大约是

    Theta( exp(1.9446 * n^(1/3)) )
    

    另请注意,将n = 500 代入上述渐近迭代次数确实会给您921498,这与@sowrov 在他们的答案中找到的迭代次数 (937500) 非常接近。

    【讨论】:

      【解决方案2】:

      isUgly 方法的复杂度是 O(log N),其中 N 是输入。因为 maxDivide 的复杂度是 O(log N) 并且调用该函数固定次数(在本例中为 3 次)不会改变复杂度。

      但是,算法的结果不能是大 O 表示法的一部分,对吧?

      是的,在计算函数的复杂度时,函数的结果是无关紧要的。

      getNthUglyNo 的时间复杂度未知或无限!对于 N=500,它运行 937500 次!

      【讨论】:

      • isUgly 可以被调用超过 N 次,所以它不会是 O(N log N)。 N 只是“发现的丑陋数字”数量的计数器目标。 isUgly 在 counter == N 之前被调用了 i 次(可能是无限的)我认为你错过了在 getNthUglyNo 函数中调用 count++ 时的代码部分。 while (n > count) 循环的每次迭代都不会增加计数,因此 while 循环实际上运行了 N 次以上,因此 isUgly 被调用了 N 次以上。
      • 啊!抱歉,我没有正确阅读该代码 - 这有点像无限循环!
      • getNthUglyNo 的复杂性肯定是有限的,因为它对所有输入都终止(忽略使用的整数的范围限制),因为显然有无限多的数字是丑陋的.
      • 那么这个无穷大的大O是什么? DDDD: