生成二进制反射格雷码

递归生成二进制反射格雷码:

需求:

​ 我们使用递归的方式来生成二进制的反射格雷码。

什么是格雷码?

​ 典型的二进制格雷码(Binary Gray Code)简称格雷码,因1953年公开的弗兰克·格雷(Frank Gray,18870913-19690523)专利“Pulse Code Communication”而得名,当初是为了通信,现在则常用于模拟-数字转换和位置-数字转换中。法国电讯工程师波特(Jean-Maurice-Émile Baudot,18450911-19030328)在1880年曾用过的波特码相当于它的一种变形。1941年George Stibitz设计的一种8元二进制机械计数器正好符合格雷码计数器的计数规律。

​ 格雷码(Gray code)曾用过Grey Code、葛莱码、葛兰码、格莱码、戈莱码、循环码、二进制反射码、最小差错码等名字,它们有的是错误的,有的易与其它名称混淆,建议不再使用它们。

粘自百度百科(手动狗头)

​ 总之,格雷码应用在各个场合,我们要做的就是生成它,它的特点就是相邻的两个数之间,只能有一位是不同的,这个需要我们进行一点儿点儿小小的脑筋。

​ 基于下面的伪代码:

  • 看到这伪代码我都傻了,因为一点儿也不好看,方法连个返回值都不给,还要自己设计,太操蛋了。

​ 因为我用的是Java,所以对于这个问题设计的返回值是List< String >。具体代码如下

/**
 * @program:算法库
 * @description:二进制反射格雷码的生成类
 */
public class BinaryReflectedGrayCode {
    
    public List<String> BRGC(int n){
        List<String> L1;
        if(n==1){
            L1 = new ArrayList<String>();
            L1.add("0");
            L1.add("1");
            return L1;
        }else{
            L1 = new ArrayList<String>(BRGC(n-1));
            List<String> L2 = new ArrayList<>();
            int len = L1.size();
            for (int i = 0; i < len; i++) {
                L2.add("1"+L1.get(len-i-1));
            }
            for(int i=0;i<len;i++){
                String s = L1.get(i);
                s = "0"+s;
                L1.remove(i);
                L1.add(i,s);
            }
            int len2 = L2.size();

            for (int i = 0; i < len2; i++) {
                L1.add(L2.get(i));
            }
            return L1;
        }
    }
}
具体的步骤是:
  • 因为是一个递归算法,所以我们要先规定递归的终点,也就是我们的初始条件,当n==1的时候,我们返回0和1两个结果
  • 后面就根据伪代码给的提示,一步一步操作即可。

​ 这里在反转这个List表单的时候,可以使用Collections.reverse(参数),进行操作,但是这个方法的返回值就void,所以最后还是返回到我们的参数中去。

​ 而在后续的步骤中,我们传进去的操作还有用,所以我们不可以将其做一个替换,那样操作的开销太大了。

public static void reverse(List<?> list) {
    int size = list.size();
    if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
        for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
            swap(list, i, j);
    } else {
        // instead of using a raw type here, it's possible to capture
        // the wildcard but it will require a call to a supplementary
        // private method
        ListIterator fwd = list.listIterator();
        ListIterator rev = list.listIterator(size);
        for (int i=0, mid=list.size()>>1; i<mid; i++) {
            Object tmp = fwd.next();
            fwd.set(rev.previous());
            rev.set(tmp);
        }
    }
}
  • 这里附上Java源码中对于这个方法的实现,还是对其底层进行了交换,所以我们没办法将其这样使用。

​ 故这里实现交换的是使用的循环,直接将其循环遍历之后,保存在我们的L2的集合中,再对L1其中的元素进行更新,这里的这个更新,应该是没有库函数可以使用,于是我们按照更新的常规操作来写,先移除再赋值,这一个操作之后,就完成了我们需要做的事情

​ 最后就是将我们的L1和L2进行合并即可,这里就遍历L2,将L2添加到L1当中。

可能,大概,也许是比较简单的一种方案了。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值