程序员的算法趣题Q47: 格雷码循环

2023-10-11 10:59

本文主要是介绍程序员的算法趣题Q47: 格雷码循环,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. 问题描述

2. 解题分析

3. 代码及测试

4. 后记


1. 问题描述

2. 解题分析

        这道题目的焦点是任意M进制数的格雷码的生成。这个确实是有难度的问题,因为它已经不是常规的算法设计问题。要求对格雷码的生成算法有了解,尤其是针对任意M进制的格雷码的生成并不是一般的二进制格雷码的生成算法的简单推广。

        以本问题为契机我特意调查了一下二进制格雷码以及任意M进制格雷码的生成算法。详情参见从二进制格雷码到任意进制格雷码(1) (2)

        我自己基于格雷码的定义给出的基于深度优先搜索的任意M进制格雷码的生成算法由于(是预先一次性生成N位M进制的所有格雷码码字)需要巨量的存储,因此并不适用于作为本题的解决方案。对于M=16,N=6的情况,总共有M**N=16**6=2**24~~10**9,这个存储量有点惊人。

        原书中给出一个提示,基于二进制格雷码生成的异或转换算法的扩展得出任意M进制格雷码生成算法。。。真的有醍醐灌顶之感!

        另外,在https://en.wikipedia.org/wiki/Gray_code中给出了一种基于迭代的方式生成M进制格雷码的算法。本文先基于这种算法给出题解。关于任意M进制格雷码生成的“异或转换”算法后面再来补充。

        M进制格雷码的详细迭代生成算法这里不再解释(事实是我没有看懂这个算法是怎么设计出来的,因此无法解释,感兴趣的伙伴自己就着代码慢慢品味吧)。

        整体的算法流程如下:


3. 代码及测试

# -*- coding: utf-8 -*-
"""
Created on Thu Oct  7 10:31:11 2021@author: chenxy
"""import sys
import time
import datetime
import math
import random
from   typing import List
# from   queue import Queue
from   collections import deque
import itertools as it
import numpy as npdef baseM_toGray(M: int, N: int, value: int) -> List:''' Parameters----------M : int. Base        N : int. Number of digitsvalue : int. Natural decimal value of the input dataReturns-------ListThe base-M gray code representation. [0]: The most siginificant digit[-1]: The least siginificant digit'''# Generate the normal base-M representation of valuebaseM = N * [0]for i in range(N-1,-1,-1):baseM[i] = value % Mvalue    = value //M# Convert the normal baseM number into the Gray code equivalent. # Note that, the loop starts at the most significant digit and goes down.gray  = N * [0]shift = 0i     = 0while i <= N-1:# The Gray digit gets shifted down by the sum of the higher digits.gray[i] = (baseM[i] + shift) % Mshift   = shift + M - gray[i];	# Subtract from base so shift is positive      i       = i + 1return gray      def cyclicSteps(M: int, N: int, start: int)->int:cur = startstep  = 0while 1:step = step + 1curGray = baseM_toGray(M,N,cur)# print(curGray)# Take curGray as normal baseM representation and calulate its valuecur   = 0scale = 1        for k in range(N-1,-1,-1):            cur = cur + curGray[k] * scalescale = scale * Mif cur == start:breakreturn stepif __name__ == '__main__':           M = 16N = 6start = 0x808080step  = cyclicSteps(M,N,start)print('start = 0x{0:6x}, step = {1}'.format(start,step))start = 0xABCDEFstep  = cyclicSteps(M,N,start)print('start = 0x{0:6x}, step = {1}'.format(start,step))

        运行结果: 

        start = 0x808080, step = 8
        start = 0xabcdef, step = 64

4. 后记

        关于格雷码生成的更多参见:

        从二进制格雷码到任意进制格雷码(1) 

        从二进制格雷码到任意进制格雷码(2)

        上一篇:Q46: 唯一的OX序列

        下一篇:Q48: 翻转得到交错排列

        本系列总目录参见:程序员的算法趣题:详细分析和Python全解

这篇关于程序员的算法趣题Q47: 格雷码循环的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/187570

相关文章

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python循环缓冲区的应用详解

《Python循环缓冲区的应用详解》循环缓冲区是一个线性缓冲区,逻辑上被视为一个循环的结构,本文主要为大家介绍了Python中循环缓冲区的相关应用,有兴趣的小伙伴可以了解一下... 目录什么是循环缓冲区循环缓冲区的结构python中的循环缓冲区实现运行循环缓冲区循环缓冲区的优势应用案例Python中的实现库

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.