谜题一 保持一致

谜题

假设有一大群人排队等待观看棒球比赛。他们都是主场球迷,每个人都戴着队帽,但不是所有人都用同一种戴法,有些人正着戴,有些人反着戴。

假定你是保安,只有在全组球迷帽子戴法一致时才能让他们进入球场,要么全部正着戴,要么全部反着戴。因为每个人对正戴和反戴的定义并不相同。因此你不能对他们说把帽子正着戴或反着戴,只能告诉他们转一下帽子。

举个栗子(我们用 F 表示正戴,B 表示反戴)

F F B B B F B B B F F B F

上面是一个13人的队伍,位置从0 ~ 12。你可以发出以下指令:

请 0 号位置的人转一下帽子,

请 1 号位置的人转一下帽子,

......

然后分别对5,9,10,12号位置的人发出同样的指令,总共要发出六次指令。

我们也可以发出这样的指令:

请 2~4 号位置的人转一下帽子,

请 6~8号位置的人转一下帽子,

请 11 号位置的人转一下帽子。

只需要 3 次指令。

我们的要求是让保安生成的命令数最少。难度更大的问题是:能否第一次沿着队伍就得正确答案呢?

算法

算法一 寻找想法相同的连续人员

计算正戴区间和反戴区间的个数, 区间数更少的即是我们要反转的帽子区间。

def pleaseconform(caps):
section = [] # 统计各区间的列表
start = 0
Fnum = 0 # 正戴区间数
Bnum = 0 # 反戴区间数
for i in range(1,len(caps)):
if caps[start] != caps[i]: # 标志着新区间的产生
section.append([start , i-1 ,caps[start]])
if caps[start]=='F':
Fnum += 1
else:
Bnum += 1
start = i
section.append([start,len(caps)-1,caps[start]]) # 6~13行代码未添加最后一个区间,这行代码用于添加最后一个区间
if caps[start]=='F':
Fnum += 1
else:
Bnum +=1
if Fnum>Bnum :
flag = 'B'
else:
flag = 'F'
for t in section:
if t[2]==flag:
if(t[0] == t[1]):
print("请"+str(t[0])+"号位置的人反转帽子")
else:
print("请"+str(t[0])+"到"+str(t[1])+"的人反转帽子") caps = ['F','F','B','B','B','F','B','B','B','F','F','B','F']
pleaseconform(caps) """
Output:
请2到4的人反转帽子
请6到8的人反转帽子
请11号位置的人反转帽子
"""
  • 我们注意到算法一的核心代码 6~13 行未添加最后一个区间,因此我们要再添加代码来完善算法,显得过于繁琐。实际上,我们只需要在 caps 列表添加一个其他元素如'M',就可以消除掉这种情况。
# 代码优化
def pleaseconform(caps):
caps.append('M')
section = []
start = 0
Fnum = 0
Bnum = 0
for i in range(1,len(caps)):
if caps[start] != caps[i]:
section.append([start , i-1 ,caps[start]])
if caps[start]=='F':
Fnum += 1
else:
Bnum += 1
start = i
if Fnum>Bnum :
flag = 'B'
else:
flag = 'F'
for t in section:
if t[2]==flag:
if(t[0] == t[1]):
print("请"+str(t[0])+"号位置的人反转帽子")
else:
print("请"+str(t[0])+"到"+str(t[1])+"的人反转帽子") caps = ['F','F','B','B','B','F','B','B','B','F','F','B','F']
pleaseconform(caps) """
Output:
请2到4的人反转帽子
请6到8的人反转帽子
请11号位置的人反转帽子
"""
算法二 单遍算法one pass

通过观察,实际上我们只需要通过 caps 列表中第一只帽子的方向,就可以得出我们需要反转的是正戴区间还是反戴区间。因为第一只帽子方向区间的个数一定大于等于另一方向的区间数。基于这一观察,能够实现一个one pass 算法。

# one pass
def pleaseconformonepass(caps):
caps.append(caps[0])
for i in range(1,len(caps)):
if(caps[i] != caps[i-1]):
if(caps[i] != caps[0]):
print("请"+str(i)+"号位置到")
else:
print(str(i-1)+"号位置的人反转帽子") pleaseconformonepass(caps) """
Output:
请2号位置到
4号位置的人反转帽子
请6号位置到
8号位置的人反转帽子
请11号位置到
11号位置的人反转帽子
"""

谜题背后

这道谜题背后的出发点是数据压缩。向同一方向的人发出的命令信息是相同的,可以被压缩为一组较少的命令,其中每一条命令指挥一组连续的人。

谜题拓展

数据压缩有多种实现方式,在思路上接近于这道习题的一种算法叫做游程编码。举一个最简单的例子最容易描述,假设有以下字符串:

WWWWWWWWWWWWWBBWWWWWWWWWWWWBBBBB

使用游程编码算法,我们可以把上述字符串压缩为一个由数字和字符构成的字符串:

13W2B12W5B

游程解码算法就是把' 13W2B12W5B '解压为原始字符串的过程。

现代计算机的压缩工具,便是利用了这种思想相关的算法。

以下是游程编码解码的具体实现:

def youcengbianma(string):
start=0
newstring = ''
for i in range(1,len(string)):
if(string[start]!=string[i]):
newstring += str(i-start)
newstring += string[start]
start=i
newstring += str(i-start+1)
newstring += string[start]
return newstring print(youcengbianma("wwweeewwwweeffeee")) """
Output:
3w3e4w2e2f3e
""" def youcengjiema(string):
num = ''
newstring = ''
for i in range(0,len(string)):
if(not string[i].isalpha()): # isalpha() 如果是字母字符,返回true
num += string[i]
else:
for j in range(0,int(num)):
newstring += string[i]
num = ''
return newstring print(youcengjiema("3w3e4w2e2f3e") """
Output:
wwweeewwwweeffeee
"""

【编程的乐趣-用python解算法谜题系列】谜题一 保持一致的更多相关文章

  1. 大牛推荐的30本经典编程书籍,从Python到前端全系列。

    注:为了方便阅读与收藏,我们也制作了30本书籍完整清单的Markdown.PDF版以及思维导图版,大家可以在实验楼公众号后台回复关键字"书籍推荐"获取. Python 系列(10本 ...

  2. python解无忧公主的数学时间编程题001.py

    python解无忧公主的数学时间编程题001.py """ python解无忧公主的数学时间编程题001.py http://mp.weixin.qq.com/s?__b ...

  3. python基础课程_学习笔记26:编程的乐趣

    编程的乐趣 编程柔术 当你坐下来,打算如何组织计划要定时,具体程序,然而,无论什么经验.在实现时间的函数的,你会逐渐学会了原来的设计,实用的新知识.我们不应该忽视沿途汲取的教训,相反,它们用于其他设计 ...

  4. Python聚类算法之基本K均值实例详解

    Python聚类算法之基本K均值实例详解 本文实例讲述了Python聚类算法之基本K均值运算技巧.分享给大家供大家参考,具体如下: 基本K均值 :选择 K 个初始质心,其中 K 是用户指定的参数,即所 ...

  5. python 排序算法总结及实例详解

    python 排序算法总结及实例详解 这篇文章主要介绍了python排序算法总结及实例详解的相关资料,需要的朋友可以参考下 总结了一下常见集中排序的算法 排序算法总结及实例详解"> 归 ...

  6. python 解压 压缩包

    转 http://m.blog.csdn.net/blog/wice110956/26597179# 这里讨论使用Python解压如下五种压缩文件: .gz .tar  .tgz .zip .rar ...

  7. Python猫荐书系列之五:Python高性能编程

    稍微关心编程语言的使用趋势的人都知道,最近几年,国内最火的两种语言非 Python 与 Go 莫属,于是,隔三差五就会有人问:这两种语言谁更厉害/好找工作/高工资…… 对于编程语言的争论,就是猿界的生 ...

  8. Scala进阶之路-面向对象编程之类的成员详解

    Scala进阶之路-面向对象编程之类的成员详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala中的object对象及apply方法 1>.scala 单例对象 ...

  9. python解压压缩包的几种方法

    这里讨论使用Python解压例如以下五种压缩文件: .gz .tar  .tgz .zip .rar 简单介绍 gz: 即gzip.通常仅仅能压缩一个文件.与tar结合起来就能够实现先打包,再压缩. ...

随机推荐

  1. 再见,Python2。你好,Python3

     文章首发自我的公众号,转载请注明出处~ ​ Python2的退场,意味着一个时代的结束 ​ 我们这一代程序员基本都接触过python2,很多人也是从python2时代一路走来的.但是,是时候说再见了 ...

  2. 【转载】你不知道的 console,让 JS 调试更简单

    对于前端工程师,肯定不会对console陌生,但是,又能深入了解多少呢? Chrome控制台-开发者工具 windows按F12, MAC按Command + Option + C或Command + ...

  3. 微信支付与支付宝支付java开发注意事项

    说明:这里只涉及到微信支付和淘宝支付 以官网的接口为准,主要关注[网关].[接口].[参数][加密方式][签名][回调] 第一步,了解自己的项目要集成的支付方式 常见的有扫码支付.网页支付.APP支付 ...

  4. $Poj2228$/洛谷$SP283\ Naptime$ 环形$DP$

    Luogu 一定要记得初始化为-inf!!! Description 在某个星球上,一天由N小时构成.我们称0-1点为第一个小时,1-2点为第二个小时,以此类推.在第i个小时睡觉能恢复Ui点体力.在这 ...

  5. 「洛谷P1233」木棍加工 解题报告

    P1233 木棍加工 题目描述 一堆木头棍子共有n根,每根棍子的长度和宽度都是已知的.棍子可以被一台机器一个接一个地加工.机器处理一根棍子之前需要准备时间.准备时间是这样定义的: 第一根棍子的准备时间 ...

  6. 《算法笔记》之基础C/C++进阶

    这一次主要讲C++不同于C的地方:类. 1.类的定义 定义一个类,本质上是定义一个数据类型的蓝图.这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可 ...

  7. Ant Design框架中不同的组件访问不同的models中的数据

    Ant Design框架中不同的组件访问不同的models中的数据 本文记录了我在使用该框架的时候踩过的坑,方便以后查阅. 一.models绑定 在某个组件(控件或是页面),要想从某个models中获 ...

  8. Codeforces Round #609 (Div. 2)前五题题解

    Codeforces Round #609 (Div. 2)前五题题解 补题补题…… C题写挂了好几个次,最后一题看了好久题解才懂……我太迟钝了…… 然后因为longlong调了半个小时…… A.Eq ...

  9. how to render html tag

    使用autoescaping If autoescaping is turned on in the environment, all output will automatically be esc ...

  10. cannot mount volume over existing file, file exists /var/lib/docker/overlay2/.../merged/usr/share/zoneinfo/UTC 解决

    问题产生原因: linux系统docker-compose.yml文件 放到 mac本启动发现启动报错 cannot mount volume over existing file, file exi ...