来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reordered-power-of-2/
博主Github:https://github.com/GDUT-Rp/LeetCode
题目:给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
示例 1:
输入:1 输出:true
示例 2:
输入:10 输出:false
示例 3:
输入:16 输出:true
示例 4:
输入:24 输出:false
示例 5:
输入:46 输出:true
提示:
1 <= N <= 1 0 9 10^9 109
解题思路: 方法一:map统计个数然后计算判断 直观想法将 n 的十进制表示视作一个字符数组,我们可以枚举该数组的所有排列,对每个不含前导零的排列判断其对应的整数是否为 2 的幂。
这可以拆分成两个子问题:
1、枚举可能包含重复字符的数组的全排列;
2、判断一个整数是否为 2 的幂(通过位运算 n&(n-1) == 0)。
class Solution { vectorGolangvis; bool isPowerOfTwo(int n) { return (n & (n - 1)) == 0; } bool backtrack(string &nums, int idx, int num) { if (idx == nums.length()) { return isPowerOfTwo(num); } for (int i = 0; i < nums.length(); ++i) { // 不能有前导零 if ((num == 0 && nums[i] == '0') || vis[i] || (i > 0 && !vis[i - 1] && nums[i] == nums[i - 1])) { continue; } vis[i] = 1; if (backtrack(nums, idx + 1, num * 10 + nums[i] - '0')) { return true; } vis[i] = 0; } return false; } public: bool reorderedPowerOf2(int n) { string nums = to_string(n); sort(nums.begin(), nums.end()); vis.resize(nums.length()); return backtrack(nums, 0, 0); } };
func reorderedPowerOf2(n int) bool { nums := []byte(strconv.Itoa(n)) sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] }) isVisiteds := make([]bool, len(nums)) var backtrack func(int, int) bool backtrack = func(idx, num int) bool { if idx == len(nums) { return isPowerOfTwo(num) } for i, ch := range nums { if num == 0 && ch == '0' || isVisiteds[i] { continue } if i > 0 && !isVisiteds[i-1] && ch == nums[i-1] { continue } isVisiteds[i] = true if backtrack(idx+1, num*10+int(ch-'0')) { return true } isVisiteds[i] = false } return false } return backtrack(0, 0) } func isPowerOfTwo(n int) bool { return n&(n-1) == 0 }Python
class Solution: def isTwoPower(self, n: int) -> bool: return n & (n - 1) == 0 def reorderedPowerOf2(self, n: int) -> bool: nums = sorted(list(str(n))) length = len(nums) vis = [False] * length def backTrack(self, idx: int, num: int) -> bool: if idx == length: return self.isTwoPower(num) for i, ch in enumerate(nums): # 当前数字是0,新的字符串是0就跳过避免前导数字为0 if num == 0 and ch == '0' or vis[i]: continue # i > 0 避免数组越界,如果前一位没被访问 && 连续两位数字相同 if i > 0 and not vis[i-1] and ch == nums[i - 1]: continue vis[i] = True if backTrack(self, idx + 1, num * 10 + ord(ch) - ord('0')): return True vis[i] = False return False return backTrack(self, 0, 0)
复杂度分析
时间复杂度:
O
(
m
!
)
O(m!)
O(m!)其中
m
=
⌊
log
10
n
⌋
+
1
m=lfloorlog_{10}nrfloor+1
m=⌊log10n⌋+1,即
n
n
n 的十进制表示的长度。
空间复杂度:
O
(
m
)
O(m)
O(m)
对于不同的整数a、b,例如a = 64, b = 46,既然 a 可以是 2 的幂,那么 b 的字符数组进行排序调整后也可以成为 2 的幂,而恰好 2 的幂的整数是有限的。
我们只需要将2的幂的数都先进行了预处理,判断十进制上每个数有多少个数,例如 256 即2、5、6的位上各为1,因此只需要对这些数进行提前预处理好存好,每一个数进行进行判断是否对应的位上有这样相等的数则知道结果。
C++string countDigits(int n) { string cnt(10, 0); while (n) { ++cnt[n % 10]; n /= 10; } return cnt; } unordered_setGopowerOf2Digits; int init = []() { for (int n = 1; n <= 1e9; n <<= 1) { powerOf2Digits.insert(countDigits(n)); } return 0; }(); class Solution { public: bool reorderedPowerOf2(int n) { return powerOf2Digits.count(countDigits(n)); } };
func reorderedPowerOf2(n int) bool { return powerOf2Digits[countDigits(n)] } var powerOf2Digits = map[[10]int]bool{} func init() { for n := 1; n <= 1e9; n <<= 1 { powerOf2Digits[countDigits(n)] = true } } func countDigits(n int) [10]int { var cnt [10]int for n > 0 { cnt[n%10]++ n /= 10 } return cnt }Python
def countDigits(n: int) -> Tuple[int]: cnt = [0] * 10 while n: cnt[n % 10] += 1 n //= 10 return tuple(cnt) powerOf2Digits = {countDigits(1 << i) for i in range(30)} class Solution: def reorderedPowerOf2(self, n: int) -> bool: return countDigits(n) in powerOf2Digits
时间复杂度:
O
(
n
)
O(n)
O(n),统计 n 的每个数字的出现次数需要
O
(
log
n
)
O(log n)
O(logn) 的时间。
空间复杂度:
O
(
1
)
O(1)
O(1)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)