刷题的日常-循环码排列

106 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情

刷题的日常-2023年2月25号

一天一题,保持脑子清爽

循环码排列

来自leetcode的 1238 题,题意如下:

给你两个整数 n 和 start。你的任务是返回任意 (0,1,2,,...,2^n-1) 的排列 p,并且满足:

  • p[0] = start
  • p[i] 和 p[i+1] 的二进制表示形式只有一位不同
  • p[0] 和 p[2^n - 1] 的二进制表示形式也只有一位不同

示例如下

输入:n = 2, start = 3
输出:[3,2,0,1]
解释:这个排列的二进制表示是 (11,10,00,01)
     所有的相邻元素都有一位是不同的,另一个有效的排列是 [3,1,0,2]

理解题意

通过题意,我们可以将信息整理如下:

  • 题目给出两个数,第一个代表返回的数组的长度要满足 2^n-1 个数,第二个代表返回数组第一个元素值
  • 要求我们返回的结果必须满足给定的规则

做题思路

看生成规则,相邻每一个数的二进制表示都只有一位不同,并且 p[0] 位置左右两边也是只相差一个位。看这描述很容易就可以想到格雷码。格雷码就是相邻两个数之间只相差一个位。

格雷码的生成规则也很简单。从0开始,翻转一次,翻转后的数的最高位变为1,这是一位格雷码。如下:

0
1

二位格雷码则是在一位格雷码上应用上面的规则,同样是翻转,翻转后的数的最高位变为1,就成了2位格雷码。如下

0         00         00
1         01         01
  -镜像->   -高位取1->
          01         11
          00         10

这样就是 0 1 3 2 四个数。那么,题目给的 n,代表就是n位格雷码,只要循环应用规则就可以了。

还有题目限制第一个数是 start,那么我们需要将生成的序列中的 start 值移动到第一个位置即可。参见题目 轮转数组

那么步骤就很简单了,如下:

  • 生成对应的格雷码
  • 找到第一个位置的数,将数组内容进行轮转

代码实现

代码实现如下: image.png image.png