Gray Code

The gray code is a binary numeral system where two successive values differ in only one bit.

Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.

For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:

00 - 0
01 - 1
11 - 3
10 - 2

Note:
For a given n, a gray code sequence is not uniquely defined.

For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.

For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.


Solution:

如果不加深入思考,可能就直接搜索了,也就是每次都试着去改变最后一个已经构造好的“01串”中的某一位,如果还没有被加入到ans集合就加进去并且将它作为最后一个已经构造好的“01串”更新。稍微需要注意的就是从已知状态只要找到一个新的合法串就需要更新查找标准了(也就是要根据刚找到的串作为标准继续搜索了)。

代码如下:

 class Solution:
# @param {integer} n
# @return {integer[]}
def grayCode(self, n):
self.n = 1 << n
self.hasGet = [False] * self.n
self.hasGet[0] = True
self.len = 1
self.str = [0] * n
self.ans = [0]
self.search(n)
return self.ans def search(self, n):
while self.len < self.n:
for i in range(n):
self.reverse(i)
num = self.getNum(n)
if self.hasGet[num]:
self.reverse(i)
else:
self.ans.append(num)
self.hasGet[num] = True
self.len += 1
break def reverse(self, i):
if self.str[i] == 1:
self.str[i] = 0
else:
self.str[i] = 1 def getNum(self, n):
ans, prod = 0, 1
for i in range(n):
if self.str[i] == 1:
ans += prod
prod *= 2
return ans

可以通过,但是效率不够高。

问题的关键在于我们只是盲目地去查找和试探对于当前最后一个“01串”改变一位后行不行,具体表现在代码中,是从最低位到最高位的顺序来试探的(for i in range(n))。

但这样的顺序在这个搜索中完全是随意无序不加思考的,也是这里导致了代码效率不够高。

我们有没有一种策略,使得我每次都可以完全确定去改变已经存在于 ans 中的某个“01串”中某一个位,使得它一定就是我们要找的合法串呢?

也就说,我们可不可以不用试探,直接去找我们需要的串,然后改变我们指定的某一位后,就是我们马上要找的新的“01串”。

得益于二进制的优美与简洁,这样的策略并不难找。

考虑这样的一种状态,我们已经找到了所有  n位及比n少的位 的二进制数,现在我们如何合法的去扩展第 n+1 位?

这个时候,整个 ans 集合已经有 2^n 个数了,此时我无论再改变 1 - n 的任何一位都不再是合法的我们要找的新串(因为所有 n 位 二进制都已经被找到了,再改变 1-n 位中任何一位都不再产生“新解”)。

所以第 2^n+1 个数一定是在第 2^n 个数基础上,将第 n+1 位置 1 后得到的新的 n+1 位 二进制串,也就是此时需要找的“新解”。

那么我们如何由这个“新解”推出更多呢?

依旧把焦点放在我们已经找到过的“旧解”上。

第 2^n 个数 与 第 2^n+1 个数是第 n+1 位不同,而 第2^n个数 与 第2^n-1个数一定是在 1..n 位中 有且仅有 一位 不相同。由此可以得知,第2^n+1个数 与 第2^n-1个数 有两位不同,即 第 n+1 位变成了 1,然后 1..n 位中有且仅有某一位不相同。此时我们如何再得到新解?

很简单,把 第 2^n-1 个数 的第 n+1 位变成 1 就是我们当前已经找到了 2^n+1 个数后的 “新解”,也就是 第 2^n+2 个数!

同理,借助“相邻数有且仅有一位不同”这样的规则,我们可以“从后向前”一路扫描我们已经得到的 2^n 个数,每次都仅仅把它们的 第 n+1 位置1,然后放心大胆的加入到 ans 集合的最后面,便是我们需要得到的 “新解” 了。这样我们利用已经得到的 “牢固的二进制翻转一位的链条” 再一次反向构造回去,打个来回,新的相同数目的解便出来了!

(对于 n+1 位二进制数,第n+1为0的某个数一定可以找到另外一个第n+1位为1的另外某个数,使得它们的 1..n 位是完全相同的。第n+1为0的数的总数也刚好与第n+1为1的数的总数是一样的,所以每次对于当前最高位的循环也都将 ans 集的规模扩大一倍)

代码如下:

 class Solution:
# @param {integer} n
# @return {integer[]}
def grayCode(self, n):
ans = [0]
for i in range(n):
p = 1 << i
s = len(ans)
while s > 0:
s -= 1
v = p | ans[s]
ans.append(v)
return ans

【LeetCode】Gray Code的更多相关文章

  1. 【leetcode】Gray Code (middle)

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  2. 【题解】【排列组合】【回溯】【Leetcode】Gray Code

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  3. 【Leetcode】【Medium】Gray Code

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  4. 【LeetCode】回溯法 backtracking(共39题)

    [10]Regular Expression Matching [17]Letter Combinations of a Phone Number [22]Generate Parentheses ( ...

  5. 【LeetCode】392. Is Subsequence 解题报告(Python)

    [LeetCode]392. Is Subsequence 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/is-subseq ...

  6. 【LeetCode】722. Remove Comments 解题报告(Python)

    [LeetCode]722. Remove Comments 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/remove-c ...

  7. 【LeetCode】831. Masking Personal Information 解题报告(Python)

    [LeetCode]831. Masking Personal Information 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzh ...

  8. 【LeetCode】Minimum Depth of Binary Tree 二叉树的最小深度 java

    [LeetCode]Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum dept ...

  9. 【Leetcode】Pascal&#39;s Triangle II

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3 ...

随机推荐

  1. C# 反射浅析

    反射是一个运行库类型发现的过程.通过反射可以得到一个给定程序集所包含的所有类型的列表,这个列表包括给定类型中定义的方法.字段.属性和事件.此外,通过反射也可以动态的发现一组给定类支持的接口.方法的参数 ...

  2. Spring MVC常用注解

    cp by http://www.cnblogs.com/leskang/p/5445698.html 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由Di ...

  3. MVC5 + EF6 完整入门教程三:EF来了

    期待已久的EF终于来了 学完本篇文章,你将会掌握基于EF数据模型的完整开发流程. 本次将会完成EF数据模型的搭建和使用. 基于这个模型,将之前的示例添加数据库查询验证功能. 文章提纲 概述 & ...

  4. 学习winform第三方界面weiFenLuo.winFormsUI.Docking.dll

    控件dockpanel中提供了几个可用的类, 重要的有两个, 一是DockPanel, 一是DockContent, DockPanel是从panel继承出来的, 用于提供可浮动的dock的子窗口进行 ...

  5. OC语言中BOOL 和 bool 区别

    1.类型不同 BOOL为int型: bool为布尔型: 2.长度不同 bool只有一个字节: BOOL长度视实际环境来定,一般可认为是4个字节: 3.取值不同 bool取值false和true,是0和 ...

  6. KindEditor的内容以Word的形式导出

    //导出按钮 protected void btn_Export_Click(object sender, EventArgs e)        {            Model.article ...

  7. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E. Goods transportation (非官方贪心解法)

    题目链接:http://codeforces.com/contest/724/problem/E 题目大意: 有n个城市,每个城市有pi件商品,最多能出售si件商品,对于任意一队城市i,j,其中i&l ...

  8. Making the Grade(POJ3666)

    题目大意: 给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调增或者单调减(不严格). 题解: 1.一开始我有一个猜想,就是不管怎么改变,最终的所有数都是原来的某个数. ...

  9. MySQL主从同步报错排错结果及修复过程之:Slave_SQL_Running: No

    起因调查: 收到大量邮件报警想必事出有因,就问同事到底发生了什么?同事登录从库查看,发现出现如下报错提示,表示与主库同步失败,一直卡在哪里,看他弄了两个多小时,问题越来越多,解决一个恢复平静了一两分钟 ...

  10. powershell字符界面的,powershell加WPF界面的,2048游戏

    ------[序言]------ 1 2048游戏,有段时间很火,我在地铁上看有人玩过.没错,坐地铁很无聊,人家玩我就一直盯着看. 2 我在电脑上找了一个,试玩了以下,没几次格子就满了.我就气呼呼的放 ...