每日一题:3.重新排序得到 2 的幂(C++)
题目:给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
解题思路:
这题重点主要是怎么将数字打乱重新组合在一起
暴力法也能做,但是效率不是很高(随后参透官方思路写了下面代码)
解题步骤:
- 高中数学里有排列组合这个知识点,把所有数字看成空格,往空格里填入能使用的各个数字得到所有的合法排列。
- 先根据题目判断是否将0放在了第一个空格,是则舍去当前排列。
- 不断的回溯,得到一个个新数字进行判断
class Solution {
public:
bool whether_PowerOfTwo(int num){ //定义whether_PowerOfTwo方法判断输入参数是否为2的幂次方(我第一次见到该方法)
return (num & (num - 1)) == 0; //2的幂的二进制都会是数字 + 0 的组合,有个规律就是,2的幂的二进制与(&)它减1的二进制结果为0
} //以8为例,8的二进制:1000,8的二进制减1:0111,它们的与(&):1000 & 0111 = 0
//若为2的幂,则 (num & (num - 1)) == 0 结果为正确,返回1否则为0,以此进行2的幂的判断
bool backTrack(int step, string &str, int num, vector<int>& sign){//定义backTrack方法(回溯方法),step为空格填入数字的个数,num为当前排列的和
if(step == str.length()) return whether_PowerOfTwo(num);//判断当前空格是否被填满,即是否得到一个新的组合,是则判断新组合是否为2的幂
for(int i = 0; i < str.length(); i ++){ //利用for循环遍历转换成字符串的数字
if(sign[i] || num == 0 && str[i] == '0' || i > 0 && !sign[i - 1] && str[i] == str[i - 1]) continue;//判断当前遍历到的数字是否已经填入了空格、判断第一个空格是否为0、判断是否会得到重复的新组合,是则跳过。
//num == 0 和 str[i] == '0'同时成立,即说明第一个空格里放入了0,因为num是每次回溯叠加的
sign[i] = 1; //当前遍历到的数字利用vector变量sign对应下标值赋值为做记号,说明当前数字填入了空格(和sum相加)
if(backTrack(step + 1, str, num * 10 + (str[i] - '0'), sign)) return true;//利用if语句进行判断顺便回溯,填入空格个数加1,num加上当前遍历到的数字,str[i] - '0'等价于将数字的字符转换成数字本身,例:'0'的ascii码为48,'5'的ascii码为53,'5' - '0' = 5
sign[i] = 0; //将当前遍历到的数字记号赋值为零,表示将其从空格拿出,下一次循环换成新的数字进行回溯组合
}
return false; //回溯结束,没有得到2的幂返回false
}
bool reorderedPowerOf2(int n) {
vector<int> sign; //定义整型vector变量sign,为遍历到的数字是否使用做记号
string str = to_string(n); //利用to_string()函数将数字n转换成字符串赋值给str
sort(str.rbegin(), str.rend()); //将str从字符值大的到小的进行排序
sign.resize(str.length()); //将sign容量大小变为str长度的大小,且默认值为0
return backTrack(0, str, 0, sign); //进行回溯得到返回的bool值
}
};
作者:yi-si-cb(倚肆)
链接:https://leetcode-cn.com/problems/next-greater-element-i/solution/xie-shi-bao-li-suan-fa-by-yi-si-cb-dsk2/