查看: 5334| 回复: 22
跳转到指定楼层
上一主题 下一主题
收起左侧

[学Python/Perl] 巨困惑! Python幂运算X**N 和 pow(X,N) 的时间复杂度到底算多少?解答加米!!!

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 小小程序媛 于 2021-12-26 20:30 编辑

在用python刷题,需要知道幂运算的时间复杂度。我自己其实也大概查了一下
说当写成 pow(X,N)math.pow(X,N) 时, 时间复杂度算作 O(1)
当写成 X**N 时,  时间复杂度算作是 O(logN)
请问以上正确吗??!!!

那幂运算写成 pow(X,N) 会更好些因为时间复杂度低是O(1)?
求谁能清晰回答一下,谢谢各位,解答保证加米



补充内容 (2021-12-27 17:54 +8:00):
亲们,为啥我会问这个呢?事情是这样的。我找实习面试的时候,面试官考了我一个题,其实很简单,就是给你一个string表示十六进制,你要转换成十进制的 int 就好了。然后我就写了下面的代码,然后面试官问我时间复杂度。我就说是O(N)啊,N是输入的string的长度。然后面试官说错了,因为这条语句 answer += value * (16 ** exp) 不是 constant time. 但后我就支支吾吾不知道怎么回答了,就挂了。  所以我只要写成 answer += value * pow(16, exp) 就算 constant time了??我真不知道咋分析时间复杂度


class Solution:

    def HexToDecimal(self, Hex: str) -> int:
        is_valid_hex = True
        answer = 0
        exp = 0
        N = len(Hex)

        for i in range( N-1, -1, -1):
            char = Hex
            if '0' <= char <= '9':
                value = ord(char) - ord('0')
            elif 'a' <= char <= 'f':
                value = ord(char) - 87 # why 87? ord('a') - 87 = 10, ord('a') = 97
            elif 'A' <= char <= 'F':
                value = ord(char) - 55 # why 55? ord('A') - 55 = 10, ord('A') = 65
            else:
                is_valid_hex = False
                break
            answer += value * (16 ** exp)
            exp += 1

        if is_valid_hex:
            return answer
        else:
            # if input is an invalid hexadecimal string, return -1
            return -1

补充内容 (2021-12-27 17:59 +8:00):
纠正  char = Hex 这行应该是 char = Hex【i】

评分

参与人数 1大米 +10 收起 理由
14417335 + 10 给你点个赞!

查看全部评分


上一篇:Leetcode premium什么时候能再有学生折扣
下一篇:请问普通数学乘法&amp;除法在python里时间复杂度多少?比如 a*b, a/b 这种回复加米!!
推荐
helloworld27 2021-12-27 14:16:12 | 只看该作者
全局:
当写成 pow(X,N) 或 math.pow(X,N) 时, 时间复杂度算作 O(1)
基本正确。math.pow 的参数会被转换成 double,然后传进标准库里的 pow 函数。根据 CPU 的不同,这个 pow 函数可能会被转换成一个计算 log 的指令,或者用多项式来拟合,运行时间一般与输入无关。
当写成 X**N 时,  时间复杂度算作是 O(logN)
半对。根据 X 和 N 的数据类型不同,X**N 有两种实现。float 版本的会用标准库里的 pow 函数,和上面差不多。整数版本的会用快速幂算法,在结果不超过 32 位整数取值范围的情况下是 O(log N)。如果结果太大,就会涉及大整数计算,会更慢。
那幂运算写成 pow(X,N) 会更好些因为时间复杂度低是O(1)?
看情况。标准库里的 pow 函数快,是因为用了有误差的拟合函数,而且 double 也是有精度损失的。快速幂可以保证结果完全准确,没有误差,而且 O(log N) 也足够好了(像 4294967296 这么大的数取 log 以后只有 32)。在我的电脑上测试,结果不超过 32 位整数范围的情况下,二者的时间基本没有区别。


评分

参与人数 5大米 +6 收起 理由
14417335 + 2 给你点个赞!
specialorange + 1 很有用的信息!
飞向月球 + 1 很有用的信息!
unclewillie + 1 赞一个
小小程序媛 + 1 太太太感激了!大神!

查看全部评分

回复

使用道具 举报

全局:
摘自stack overflow

pow and ** do integer exponentiation if their arguments are integers. (Python 3 has automatic bignum support, so, for example, a ** b always gives the exact integral result, even if a or b are very large.) This takes O(log(b)) multiplications with exponentiation by squaring, but bignum multiplication isn't constant time, so the time complexity depends on details of the multiplication algorithm used. (Also, Python doesn't quite use exponentiation by squaring, but what Python does use still takes O(log(b)) multiplications.)
math.pow, on the other hand, is different. It always does floating point exponentiation and is always O(1). That O(1) complexity isn't because it's any more efficient than pow or **; it's because floating point sacrifices accuracy and range. For cases where the non-constant complexity of integer exponentiation actually matters, math.pow will give much less precise results or throw an OverflowError

评分

参与人数 3大米 +4 收起 理由
14417335 + 2 很有用的信息!
yxli2123 + 1 给你点个赞!
小小程序媛 + 1 赞一个

查看全部评分

回复

使用道具 举报

推荐
shaosy 2021-12-28 00:03:30 | 只看该作者
全局:
墨绿 发表于 2021-12-27 20:52
代码是对的跟面试官核对过,但我不会分析时间复杂度了。思路把我引导写成了这种代码,肯定也有不用幂运算 ...

你这个从后往前遍历,每次乘n。n初始化为1,每次乘完了以后n*=16就行了啊... 我个人认为这里无论你用**还是pow面试官都会挂你,因为如果面试官不了解python(比如,他常用c++),他根本不会去了解这俩的区别。从显然的角度(或者从c++的角度),pow显然不是常数级别复杂度。
回复

使用道具 举报

全局:
可能pow(x, N)会被写成 e^(N * log(x)),然后被算成某些基础函数取值的复杂度?
回复

使用道具 举报

🔗
babybear68 2021-12-27 12:40:27 | 只看该作者
全局:
  1. import math
  2. import numpy as np
  3. import time


  4. nums = np.random.randn(1000000)
  5. times_pow = []
  6. times_math = []
  7. times_op = []

  8. for num in nums:
  9.     t = time.time()
  10.     pow(num, 64)
  11.     times_pow.append(time.time() - t)
  12.     t = time.time()
  13.     math.pow(num, 64)
  14.     times_math.append(time.time() - t)
  15.     t = time.time()
  16.     num ** 64
  17.     times_op.append(time.time() - t)

  18. print(np.mean(times_pow))
  19. print(np.mean(times_math))
  20. print(np.mean(times_op))
  21. print(np.mean(times_op) / 6)
复制代码
4.969379901885987e-07
2.6874446868896486e-07
4.787726402282715e-07
7.979544003804525e-08

评分

参与人数 2大米 +2 收起 理由
14417335 + 1 给你点个赞!
小小程序媛 + 1 欢迎分享你知道的情况,会给更多积分奖励!

查看全部评分

回复

使用道具 举报

🔗
 楼主| 小小程序媛 2021-12-27 12:43:50 | 只看该作者
全局:
babybear68 发表于 2021-12-26 20:40
4.969379901885987e-07
2.6874446868896486e-07
4.787726402282715e-07

没太看懂这想表达什么意思……
回复

使用道具 举报

🔗
 楼主| 小小程序媛 2021-12-27 12:45:00 | 只看该作者
全局:
newcodingfarmer 发表于 2021-12-26 20:41
摘自stack overflow

pow and ** do integer exponentiation if their arguments are integers. (Python 3  ...

您的这个我看过了呢,所以这就是 a**b 时间复杂度算 O(logb),pow(a,b)的话算O(1) 咯?
回复

使用道具 举报

🔗
babybear68 2021-12-27 12:56:51 | 只看该作者
全局:
小小程序媛 发表于 2021-12-26 23:43
没太看懂这想表达什么意思……

意思就是如果pow是O(1)的话 以浮点数为底数的**运算符不太可能是O(log(n))的 以整数为底数的结果类似如下:
3.931338787078857e-07
2.75949239730835e-07
3.785521984100342e-07
6.309203306833904e-08

评分

参与人数 1大米 +1 收起 理由
小小程序媛 + 1 欢迎分享你知道的情况,会给更多积分奖励!

查看全部评分

回复

使用道具 举报

🔗
 楼主| 小小程序媛 2021-12-27 13:03:53 | 只看该作者
全局:
babybear68 发表于 2021-12-26 20:56
意思就是如果pow是O(1)的话 以浮点数为底数的**运算符不太可能是O(log(n))的 以整数为底数的结果类似如下 ...

那所以pow(X,N) 和 X**N 的时间复杂度是多少呢……不好意思我基础薄弱,给您加米了……
回复

使用道具 举报

回复

使用道具 举报

🔗
babybear68 2021-12-27 13:20:00 | 只看该作者
全局:
小小程序媛 发表于 2021-12-27 00:03
那所以pow(X,N) 和 X**N 的时间复杂度是多少呢……不好意思我基础薄弱,给您加米了……

我觉得具体是多少不是很重要 只需要知道三者的复杂度应该是一样的就可以 在做题的时候随便用哪一个 面试的时候最好写** 因为比较简洁易读 实际的复杂度可能和底层代码甚至硬件加速有关 除非面试的是相关的岗位 不太可能会问到你这个问题 甚至面试官都不一定清楚有什么区别 你给出的解的复杂度可以理解为进行多少次幂运算 比如说O(n^2)次幂运算 而幂运算具体的复杂度和你给出的解没什么关系 比如说你的解可以进一步优化到O(n*log(n))次幂运算 都是以一次幂运算当作计量单位的 如果可以以比如说加法运算当作计量单位 那说明你的解法可能有问题

评分

参与人数 2大米 +3 收起 理由
14417335 + 2 给你点个赞!
小小程序媛 + 1 给你点个赞!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表