[LeetCode] 格雷码(Gray Code)

格雷码是一种数字排序系统,其中的所有相邻整数在它们的二进制数字表示中只有一个数字不同。现要求打印出二进制比特数是n的所有格雷码。例如,n=2,所有的格雷码是0,1,3,2(对应二进制表示是00,01,11,10)。

思路一:

如果仔细观察格雷码的规律,可以发现,对于n比特的格雷码,前2^(n-1)个格雷码的前n-1比特和后2^(n-1)个格雷码的前n-1比特是对称的,前2^(n-1)个格雷码的第n比特和后2^(n-1)个格雷码的第n比特是相反的。例如,3比特的格雷码,如下所示:

0-0-0

0-0-1

0-1-1

0-1-0

1-1-0

1-1-1

1-0-1

1-0-0

可以发现,前4个格雷码的前2个比特和后四个格雷码的前2个比特是对称的,前4个格雷码的第3个比特和后四个格雷码的第3个比特是相反的。

有了这个规律,我们可以借助栈和队列来做这个题。设stack1存了所有的j比特格雷码。现在创建一个stack1的副本stack2,把stack2里所有格雷码都pop到另外一个队列queue里,然后依次从队列头部取元素,把这个元素和(1<<(j-1))进行异或,把异或结果push到stack1里。这个时候stack1里就存有所有的(j+1)比特格雷码。

    vector<int> grayCode(int n) {
        
        vector<int> vec;
        vec.push_back(0);
        if(n==0) return vec;
        
        vec.push_back(1); // if n==1, vec=[0,1]
        
        if(n>1) // if n>1
            for(int i=1; i<n; i++)
            {
                int sz = vec.size();
                for(int j=sz-1; j>=0; j--)
                {
                    int num = vec[j];
                    num = num|(1<<i);
                    vec.push_back(num);
                }
            }
            
        return vec;
    }

思路二:

The tricky part of this question is to recognize the recursive structure here. For n = 0, sol = [0], that’s the base case. For recursive step, let’s take n = 2 and n = 3 as examples. n = 2, sol = [0, 1, 3, 2]; n = 3, sol = [0, 1, 3, 2, 6, 7, 5, 4]. Look at these two solutions, we see when n = 3, we add 4 more elements [6, 7, 5, 4] and they are just [2+4, 3+4, 1+4, 0+4]. That is sol(n+1) = sol(n) + [ reverse(sol(n)) + 2^(n) ].

class Solution {
public:
    vector<int> grayCode(int n) {
        if(n == 0) {
            vector<int> sol;
            sol.push_back(0);
            return sol;
        } else {
            vector<int> previous = grayCode(n - 1);
            vector<int> sol(previous);
            for(int i = previous.size() - 1; i >= 0; --i) {
                sol.push_back((int)pow(2.0, n - 1) + previous[i]);
            }
            return sol;
        }
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值