每日一题:3.重新排序得到 2 的幂(C++)

每日一题:3.重新排序得到 2 的幂(C++)

题目:给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。

解题思路:
这题重点主要是怎么将数字打乱重新组合在一起
暴力法也能做,但是效率不是很高(随后参透官方思路写了下面代码)

解题步骤:

  1. 高中数学里有排列组合这个知识点,把所有数字看成空格,往空格里填入能使用的各个数字得到所有的合法排列。
  2. 先根据题目判断是否将0放在了第一个空格,是则舍去当前排列。
  3. 不断的回溯,得到一个个新数字进行判断
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/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倚肆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值