给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
示例 1:
输入:1
输出:true
提示:
1 <= N <= 10^9
方法一:穷举
由提示可知给定的 N 在int型范围内,那么对于最取巧的方法来说,不妨在开始就枚举完所有的 2^n 的值并将位数从小到大进行排序(如 512 -> 125),在输入数值时也进行相同的位数排序处理并直接与先前储存的结果进行比较,直接可的解。
方法二:全排列
那么对于像博主这样的老实人,当然是全排列所有可能的结果并利用二进制特性一一进行位运算检验合法性,其中需要特别注意的是全排列的剪枝判定:
- 当该枚举数在本次排列中被使用过时跳过
(废话 - 当处于首位且枚举数为0时跳过
- 当当前枚举数与前一项数相同,且前一项数未被使用时(此情况下相当于由两个相同的枚举项竞争同一待填位数)
为了确保第三点能够成功执行,我们需要将输入的数字进行排序,而又因为我们进行了全排列来检索所有可能性所以对原有数据的打乱并不会影响结果的正确性。
private boolean canBe = false;
private char[] nums;
public boolean reorderedPowerOf2(int n) {
this.nums = Integer.toString(n).toCharArray();
Arrays.sort(nums);
dfs(0, 0, new boolean[nums.length]);
return canBe;
}
private void dfs(int index, int value, boolean[] used) {
if (canBe) return;
if (index == nums.length) {
if (lawful(value)) canBe = true;
return;
}
for (int i = 0; i < nums.length; ++ i) {
if (used[i] || (index == 0 && nums[i] == '0') || (i != 0 && nums[i] == nums[i-1] && !used[i-1])) continue;
used[i] = true;
dfs(index+1, value*10+nums[i]-'0', used);
used[i] = false;
}
}
public static boolean lawful(int number) {
boolean lawful = true;
int temp = number;
while (temp >> 1 != 0) {
if ((temp & 1) == 1) {
lawful = false;
break;
}
temp >>= 1;
}
return lawful;
}