谜题一 保持一致

谜题

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

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

举个栗子(我们用 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
"""

最新文章

  1. 理解Docker(8):Docker 存储之卷(Volume)
  2. python之消息队列
  3. R语言实战(二)数据管理
  4. 使用dd命令克隆整个系统(转)
  5. jackson对多态or多子类序列化的处理配置
  6. .net截取两个字符串中间的内容
  7. sql server 发布时提示'dbo.sysmergepublications'无效的解决办法
  8. apache_fileupload实现文件上传_上传多个文件
  9. MDCC 2014移动开发者大会 小礼品展商活动
  10. 在线制作css动画——cssanimate
  11. java数据写入Excel
  12. spring是如何控制事务
  13. STL::unordered_map/unordered_multimap
  14. java常见反编译工具
  15. 使用spin.js优化等待ajax返回时的页面效果
  16. 应用jfinal时要注意区分Db.query和Db.find
  17. Centos6.5 安装配置docker
  18. oracle数据库之触发器
  19. 网络设备之pci_driver
  20. sql server数据库字段名要注意不能叫file

热门文章

  1. spring boot(二)热部署
  2. alpha week 1/2 Scrum立会报告+燃尽图 06
  3. QTableView 控件的简单使用
  4. 【题解】BZOJ5093图的价值(二项式+NTT)
  5. leetcode.310最小高度树
  6. CentOS8安装fastdfs6.06
  7. 1024 科学计数法 (20 分)C与Java
  8. apache相关实验-2
  9. ThreadLocal解析:父线程的本地变量不能传递到子线程详解
  10. 【一起学源码-微服务】Hystrix 源码二:Hystrix核心流程:Hystix非降级逻辑流程梳理