本题出自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
```
时间复杂度
需要检查多少个 2 的幂?
- 因为题目说 n 最大是 10 亿(10^9)
- 2 的 30 次方大约是 10 亿
- 所以最多检查 30 个数字
每次检查要做什么?
- 把数字转成字符串(比如 64 变成 "64")
- 对字符串排序("64" 变成 "46")
- 比较两个字符串是否相同
总的时间复杂度:
- 检查 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),空间复杂度是常数级(集合大小固定不变)。