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. 关闭显示器API及命令

    window下命令powercfg /change "Home/Office Desk" /moniter-timeout-ac 1C#中实现[DllImportAttribute ...

  2. Jquery mobile 新手问题总汇

    1页面缩放显示问题 问题描述: 页面似乎被缩小了,屏幕太宽了. 解决办法: 在head标签内加入: <meta name="viewport" content="w ...

  3. Oracle 数据库特殊查询总结

    1. 查询本节点及本节点以下的所有节点: select * from table1 c start with c.p_id='0000000' connect by prior c.id=c.p_id ...

  4. Mindmanager安装

  5. java Resource

    ClassPathResource: String resource = ""; //相对路径 Resource resource = new ClassPathResource( ...

  6. php实现递归的三种方式: 遍历文件夹实例

    递归函数是我们常用到的一类函数,最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去.实现递归函数可以采取什么方式呢?本文列出了三种基本方式.理解其原来需要一定的基础知识 ...

  7. springMVC中实现servlet依赖注入

    记录一下开发过程中遇到的问题: 首先看一下这个帖子: http://blog.csdn.net/gaogaoshan/article/details/23540129 由于我使用的是springMVC ...

  8. EXE加锁器 只是思路

    代码有点乱 但是我不想整理 // AddBoxDlg.cpp : 实现文件 // #include "stdafx.h" #include "AddBox.h" ...

  9. JSP页面中的精确到秒的时间控件

    技术:Struts1+jsp+MSql 需求:ncmgt网络监控系统中显示用户的操作日志,并且根据操作时间查询用户的详细操作记录.时间精确到秒 大致效果如下.上图! 大家可以清晰的看到.红色画线部分就 ...

  10. WebView 的使用----android 网络连接处理分析

    在Android中,可以有多种方式来实现网络编程: 创建URL,并使用URLConnection/HttpURLConnection 使用HttpClient 使用WebView 创建URL,并使用U ...