89. Gray Code --迭代 和 back tracking 两种方法

产生格雷码,格雷码就是前后 两个数在二进制上只有一个bit 的差别

先看看格雷码的规律: 

n =0,  [0]

n=1, [0 1]

n=2:     00

            01

            11

            10

n=3:    000

           001

           011

           010

-----------------------------

           110

           111

           101

           100

可以发现规律, 比如 n=3 时相比于 n=2 时, 前面 4个数字和 n=2 时一样, 后四个数字 就是 在n=2 时结果从后往前 前2 bits 不变, 然后在最高位上添加1, 因此很容易得到一个迭代的算法,code 如下:

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> result = new ArrayList<>();
        if(n <0) return  result;   
        result.add(0);
        for(int i=0; i<n; i++){
           int inc = 1<<i;
           int size = result.size(); 
           for(int j=size-1; j>=0;j--){
               result.add(result.get(j)+inc);
           } 
        }
        return result;    
    }
}

code 虽然简单,但一开始被我写错了两处:

1.  2^n 写成了 2<<n, 正确的是 1<<i

2.  for(int j = result.size()-1; j>=0; j--) : 因为 result.size() 会不断增加,所以得先取出 size 。

back tracking 解法:

画一个递归数就明白了: 本质上就是一个二叉树,问题是每次到底是先放 0 还是先放1。 观察可以发现规律: 如果当前路径下  1的个数为 偶数个,就放 left =0, right =1, 如果当前路径下 1的个数为奇数,就放left = 1, right =0.

为了统计 当前路径下 1的个数,设计了一个Node 节点,里面的count 表示当前 1的个数。

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> result = new ArrayList<>();
        dfs(new Node(), result, n);
        return result;
    }
    
    private void dfs(Node curResult,List<Integer> result, int n){
        if(curResult.list.size() == n){
            int sum=0;
            for(int i=0; i<n; i++){
                sum += curResult.list.get(n-i-1) << i;
            }
            result.add(sum);
            return;
        }
        
       
         if(curResult.count%2 ==0){ // 1的个数为偶数个,先放0 再放1
             //left :
             curResult.list.add(0);
             dfs(curResult,result,n);
             curResult.list.remove(curResult.list.size()-1);
             
             //right
             curResult.list.add(1);
             curResult.count ++;
             dfs(curResult,result,n);
             curResult.list.remove(curResult.list.size()-1);
             curResult.count --;
         }
        else {   // 1的个数为奇数个, 先放1, 再放0
             //left
             curResult.list.add(1);
             curResult.count ++;
             dfs(curResult,result,n);
             curResult.list.remove(curResult.list.size()-1);
             curResult.count --;            
            
             //right 
             curResult.list.add(0);
             dfs(curResult,result,n);
             curResult.list.remove(curResult.list.size()-1);   
        }
        //right tree
    }
}

class Node {
    List<Integer> list;
    int count;
    Node(){
        list = new ArrayList<>();
        count = 0;
    }
}

猜你喜欢

转载自www.cnblogs.com/keepAC/p/9944510.html
今日推荐