Leetcode——重新排序得到 2 的幂

Posted Yawn__

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——重新排序得到 2 的幂相关的知识,希望对你有一定的参考价值。

1. 重新排序得到 2 的幂

(1)朴素枚举

//java
class Solution 
    public boolean reorderedPowerOf2(int n) 
        for(int i = 1;i < (int)1e9;i *= 2)
            if(check(i,n)) return true;   //枚举所有2的幂,一一与n进行词频比对
        
        return false;
    
    public boolean check(int i,int n)
        int[] cnts = new int[10];    //统计每个数字的出现次数
        while(i != 0)
            cnts[i%10]++;           //用i中每个数字的出现次数初始化cnts
            i /= 10;
        
        while(n != 0)              //看n中数字的出现次数能不能匹配上
            if(cnts[n%10] == 0) return false;  
            else
                cnts[n%10]--;      
            
            n /= 10;
        
        for(int j = 0;j < 10;j++)  //检查cnts数组是否全部为0,如果有不为0的位置说明该数字没匹配上
            if(cnts[j] != 0) return false;  
        
        return true;
    

(2)DFS

对 n 进行重排,然后检查重排后的数值是否属于 2 的幂。

由于 2 的幂数固定,我们可以先通过「打表」将范围落在 [1, 1e9] 以内的 2 的幂预处理出来,这样我们可以在 O(1)的复杂度内判断某个数是否为 22 的幂。

//把范围内2的冥存入set中,再dfs暴搜即可
class Solution 
    static Set<Integer> set = new HashSet<>();
    static  
        for (int i = 1; i < (int)1e9+10; i *= 2) set.add(i);
    

    //统计每个数字的数字位数和出现次数
    int m;
    int[] cnts = new int[10];   
    public boolean reorderedPowerOf2(int n) 
         //用n中每个数字的出现次数初始化cnts
        while (n != 0) 
            cnts[n % 10]++;
            n /= 10;
            m++;
        
        return dfs(0, 0);
    

    private boolean dfs (int u, int cur) 
        //看数字的位数能不能匹配上
        if (u == m) return set.contains(cur);
        
        for (int i = 0; i < 10; i++) 
            //检查cnts数组是否全部为0,如果有不为0的位置说明该数字没匹配
            if (cnts[i] != 0) 
                cnts[i]--;
                if ((i != 0 || cur != 0) && dfs(u + 1, cur * 10 + i)) return true;
                cnts[i]++;
            
        
        return false;
    

(3)打表 + 词频统计

对于(1)我们发现复杂度上界取决于对 n 的重排,同时数据范围内的 2 的幂数量很少。

因此有效降低复杂度(避免重排)的做法是,直接枚举所有的 2 的幂 x,检查 x 的词频是否与 n 相同。

class Solution 
    static Set<Integer> set = new HashSet<>();
    static 
        for (int i = 1; i < (int)1e9+10; i *= 2) set.add(i);
    
    public boolean reorderedPowerOf2(int n) 
        int[] cnts = new int[10];
        while (n != 0) 
            cnts[n % 10]++;
            n /= 10;
        
        int[] cur = new int[10];
        //out:for是标签,用于跳出循环的。continue out / break out用于跳出包含它的最内层循环,continue out / break out可以直接跳出被out标记的循环。
        out:for (int x : set) 
            Arrays.fill(cur, 0);
            while (x != 0) 
                cur[x % 10]++;
                x /= 10;
            
            for (int i = 0; i < 10; i++) 
                if (cur[i] != cnts[i]) continue out;
            
            return true;
        
        return false;
    

以上是关于Leetcode——重新排序得到 2 的幂的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 869. 重新排序得到 2 的幂

《LeetCode之每日一题》:194.重新排序得到 2 的幂

Leetcode(869)-重新排序得到 2 的幂

869. 重新排序得到 2 的幂枚举

LeetCode 496. 下一个更大元素 I / 301. 删除无效的括号 / 869. 重新排序得到 2 的幂

Leecode 869. 重新排序得到 2 的幂——Leecode每日一题系列