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. php学习函数

    1defined和define区别 2.dirname(__FILE__) 3.set_include_path 4.get_include_path 5.realpath() 6.require_p ...

  2. 做为一名PHP程序员,应该关注的互联网IT大牛!

    俗话说:“读万卷书不如行万里路,行万里路不如高人指路”,做为一名新人,以后的路还很长,多年你的成就取决于今天的自己付出,选中自己的方向比什么都重要,关注大牛,向他们学习,才不会迷失自己! 1.惠新宸( ...

  3. Web应用安全十大主动安全措施

    这几天有空参加了360主办的第一届互联网安全大会(ISC 2013),除了现场看到FREEBUF现场微博号发的众多妹子之外,也听到了很多有趣的议题,比如TK分享的通过网络运营商缓存服务器偷渡,只需一台 ...

  4. KMP算法解析(转自图灵社区)

    KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...

  5. java 选择排序

    import java.util.Scanner; public class SelectionSort { public static void sort(int[] a, int n){ if(n ...

  6. Redis常用命令入门3:列表类型

    列表类型 列表类型也是一个我们很长要用到的一个类型.比如我们发博客,要用到博客列表.如果没有列表我们就只能遍历键来获取所有文章或一部分文章了,这个语法是keys,但是这个命令需要遍历数据库中的所有键, ...

  7. [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例

    懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...

  8. 获取checkbox后面的文本内容

    http://alygle.blog.51cto.com/1922399/669040 <head> <meta http-equiv="Content-Type" ...

  9. Command Pattern 命令模式

    定义: 命令模式将‘请求’封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作. 类图 如上图所示:Command类是用来声明执行操作的接口:ConcreteCom ...

  10. Android中的多线程编程

    问题 Android的UI也是线程不安全的,如果要更新应用程序里的UI元素,必须在主线程中进行,否则就会抛异常.比如用一个Button的onClick函数去更新界面上的元素,就会得到一个CalledF ...