每日一题:重新排序得到 2 的幂

本题出自869.重新排序得到 2 的幂

今后的每日一题,我将会在这个文章写完之后引入时间复杂度,没有时间复杂度的计算,单纯的说算法是不完美的。我将统一使用Python来解题。如果大家有其他语言需要,可以文章下面评论或者私信告诉我。


题目 

给定正整数 n ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。

如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false

示例 

示例 1:

输入:n = 1
输出:true

示例 2:

输入:n = 10
输出:false

提示:

  • 1 < n < 10的9次幂

解题思路1

首先,2的幂那是不是指的是2^0, 2^1, 2^2, ......., 2^N?

那么好的,我们先想象我们有一个数字,是23。

那么23是不是可以重新排列为32?

32,是不是2的5次方?

既然知道了题目在询问什么,做题第一步,是不是先想这个数字,它能不能重新排列?

比如 46 和 64,它们都有一个 4 和一个 6

比如 123 和 321,它们都有一个 1、一个 2、一个 3

把两个数的数字都排序,如果结果相同,就能互相重排列

那么解题方法就出来了

1.我们先对数字进行重排序

2.生成所有可能的2的幂的数

3.把每个 2 的幂的数字也排序

4.如果发现某个 2 的幂排序后和 n 排序后相同,返回 true

为了守护爱与正义与和平,我这里给出思路示例

  • 输入 n = 46
  • 46 排序后是 "46"
  • 检查 2 的幂:
    • 1 → "1" (不匹配)
    • 2 → "2" (不匹配)
    • 4 → "4" (不匹配)
    • .....................
    • 64 → "46" (匹配了!)
  • 返回 true

代码

```python
class Solution(object):
    def reorderedPowerOf2(self, n):
        """
        :type n: int
        :rtype: bool
        """
        # 将数字转换为排序后的字符串作为特征
        def getSortedDigits(num):
            return ''.join(sorted(str(num)))
        
        # 获取n的数字特征
        n_sorted = getSortedDigits(n)
        
        # 检查所有可能的2的幂
        power = 1
        while power <= 10**9:  # n最大为10^9
            if getSortedDigits(power) == n_sorted:
                return True
            power *= 2
        
        return False
```

时间复杂度

  1. 需要检查多少个 2 的幂?

    • 因为题目说 n 最大是 10 亿(10^9)
    • 2 的 30 次方大约是 10 亿
    • 所以最多检查 30 个数字
  2. 每次检查要做什么?

    • 把数字转成字符串(比如 64 变成 "64")
    • 对字符串排序("64" 变成 "46")
    • 比较两个字符串是否相同
  3. 总的时间复杂度

    • 检查 30 个数字,每个数字最多 10 位
    • 时间复杂度大约是 O(30 × 10) = O(300)
    • 用专业术语说是 O(log² n),但你可以理解为"很快"

解题思路2

我们关心的不是数字的“顺序”,而是“用了哪些数字,以及每个数字用了几次”。

把一个数变成字符串,再把字符排序,比如:

  • 128 , 排序后是 "128"
  • 821 , 排序后也是 "128"
  • 它们的“数字组成”一样,只是顺序不同,所以是一类。
  • 先把一堆 2 的幂(像 1, 2, 4, 8, 16, 32, 64, ...)都转成字符串并排序,存到集合中。

这样,我们把 n 也转成字符串并排序,看它是否在集合里:

  • 如果在,说明 n 的数字可以重排成那个 2 的幂,返回 True。
  • 如果不在,说明无论怎么重排都不可能是 2 的幂,返回 False。
  • 不用担心“前导 0”的问题:我们是在对比“数字组成”。一旦匹配到某个 2 的幂,那就直接重排成那个幂本身(它本身不以 0 开头),自然是合法的。

代码

class Solution(object):
    def reorderedPowerOf2(self, n):
        """
        :type n: int
        :rtype: bool
        """
        # 1) 把 n 转成字符串并排序,得到它的“指纹”(数字组成不变,只是顺序变了)
        sig = "".join(sorted(str(n)))
        
        # 2) 预先把若干个 2 的幂也做同样处理,存到一个集合里
        #    range(61) 表示从 2^0 到 2^60,数量不多,但足够覆盖
        pow2_sigs = {"".join(sorted(str(1 << k))) for k in range(61)}
        
        # 3) 如果 n 的“指纹”在集合里,说明可以重排成某个 2 的幂
        return sig in pow2_sigs

时间复杂度

  • 设 d 是 n 的位数(比如 123 有 3 位)。
  • 把 n 的位数排序需要 O(d log d)。
  • 预处理 2 的幂的“指纹”只有固定的 61 个,长度最多几十位,整体当常数时间。
  • 因此总时间复杂度是 O(d log d),空间复杂度是常数级(集合大小固定不变)。

制作不易,感谢你的点赞、收藏与关注 ovo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值