1. 程式人生 > >89. Gray Code --迭代 和 back tracking 兩種方法

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;
    }
}