leetcode 89. 格雷编码

归纳法 (c++)

class Solution {
public:
    vector<int> grayCode(int n) 

       {
        vector<int> a;
        a.reserve(1 << n);
        a.push_back(0);
        for (int i = 1; i <= n; i++) {
            int num = a.size();
            for (int j = num - 1; j >= 0; j--) {
                a.push_back(a[j] | (1 << (i - 1)));
            }
        }
        return a;
    }
};

个人注解:

 

class Solution {

public:

    vector<int> grayCode(int n) {

        vector<int> a;

        //reserve():表示容器预留空间,但不是真正的创建对象,需要通过insert()或push_back()等操作创建对象

        a.reserve(1 << n);//左移:0010->0100,题目中1 << n即为预留2的n次个位置

        a.push_back(0);//将0压入,后续会在0后压入其他数

        /*n每增加1,数组长度就增加一倍,但是n的数列可以由n-1的数列本身加上处理后的反转n-1的数列这两个数列相加得到,从第一个0进行处理从而得到n=1(2^1个数)的数列,以此类推*/

        for (int i = 1; i <= n; i++) {

            int num = ret.size();

//size:指当前容器所存储的元素个数,num一直在变,最开始只有0一个元素,则为1

            for (int j = num - 1; j >= 0; j--) {

/*j表示当前长度的最后一个,因为想得到n位的格雷码需要n-1位的和其翻转数列的处理数列相加,要先翻转,所以从后向前表示翻转这一处理*/

                a.push_back(a[j] | (1 << (i - 1)));

                // |为按位或,如A = 0011 1100,B = 0000 1101,A|B = 0011 1101

            }

/*将当前ret中每一个数二进制的情况下最前面的一位变成1,从后向前操作,再依次压入,从一个数到两个数,进行此操作,则二进制有一位不同,满足题目要求,两个数变成四个数,先从两个数中的第二个进行处理然后压入a,则第三个数与第二个数二进制恰好有一位不同,以此类推,当j向前算到n-1位格雷码序列的第一个对应的是n-1位反转后的最后一个,同样进行此操作,而这两位是n位格雷码数组的第一个和最后一个,也恰好一位不同,这种处理方式可以满足题目要求*/

        }

        //以n=2为例子,最开始只有0,j=0,进行操作后压入1,得到0,1满足题目上各种要求

        //之后i=2,j=1,a.push_back(a[1] | (1 << (1))),1左移得到10,为两位,a[1]的值1会自动在前面补上一个0也变成两位,括号中为01|10,得到11即为3并压入

                   /*等于把01最前面的0变成了1,且相邻的两个恰有一位不一样,之后j--,00|10得到10,即为2,压入*/

        /*无需担心不满足题目条件,在从n-1到n时:n-1个先反转,本身是满足相邻不同的,之后从n-1的最后一个数开始处理并压入,则这两个数只有二进制代码中最前面一位(新的部分会在二进制码最前面再加一位1,原来的会自动补上一个0让二者位数相等)不同,其余的没有区别,而后半部分整体等于把前半部分翻转然后在最前面新加一位0,其余不变,再把二者相加,所以不会有区别*/

        return a;

    }

};

/*格雷码每加1都会让二进制码多一位,比如n=1对应的是2^1个数0,1,n=2则变成00,01,11,10即为0,1,3,2,以此类推n=3时则为三位数,而n由1到2的过程就是先把0,1反转为1,0再把0和1前面都再加上一位1变成11,10,之后本身的0,1会自动在前面加上一位0变成00,01,二者相加得到00,01,11,10,每个都有两位二进制,且处理过程得到的结果满足题目要求,相邻的有一位不一样,首尾有一个不一样,之后转化为十进制即可,其余的以此类推*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值