我有N张牌,前面和后面都写有数字。现在,我可以翻转任何一张牌,使其底部成为顶部。
考虑到卡片顶部和底部的数字,我需要找到最少的移动次数,这些移动可以使至少一半的卡片在其顶部显示相同的数字。
如果无法这样做,那么也要告诉它是不可能的。
示例:假设我们有3张牌并表示为(顶部的数字,底部的数字)
卡1:(3,10)
卡2:(10,3)
卡3:(5,4)
现在,这里的minmum移动只有1,因为我们可以翻转第一张牌,使得顶部的数字变为10.由于三张牌中的两张在他们的顶部有相同的数字(10),我们不需要改变任何东西否则,答案是1。
答案 0 :(得分:1)
从您的问题来看,以下几点并不完全清楚:
我会选择以下内容:
i
,计算出现的卡片的m(i)
数量(顶部或底部); m(i)
大于N/2
则失败i
,请计算卡片中top(i)
的数量,如果它出现在顶部; c
m(c) - top(c)
最小的数字; m(c) - top(c)
,c
位于底部,但不在顶部。答案 1 :(得分:0)
N
是卡的数量。top(v)
计算v在v=0..N-1
bottom(v)
计算v出现在底部的频率。top(v)
v
top(v)
top(v)+bottom(v) >= N/2
v
是你的结果,否则从排序列表中选择下一个这是Python中的算法:
from collections import defaultdict
def cardflip( cards ):
# 'tops' maps the value to the count of cards
# showing that value on top
tops = defaultdict(int)
# 'bottoms' maps the value to the count of cards
# showing that value on bottom
bottoms = defaultdict(int)
for c in cards:
topvalue = c[0]
tops[topvalue] += 1
bottomvalue = c[1]
if bottomvalue != topvalue:
# if it's the same on both side we ignore the bottom
bottoms[bottomvalue] += 1
tops[bottomvalue] += 0
# topcounts is a list of pairs (value, count)
topcounts = list(tops.items())
# sort it by count, the biggest first
topcounts.sort( key = lambda x : -x[1] )
for (v, c) in topcounts:
if (c + bottoms[v]) * 2 >= len(cards):
final = v
break
else:
print( "there is no result" )
return
print( "value=", final, "moves=", (len(cards)+1)//2 - tops[final] )
cardflip( [ (3,10), (10,3), (5,4) ] )
cardflip( [ (1,3), (2,3), (4, 5), (6, 7), (9,3), (11,2)] )
如果您没有可用的Python,可以在此处尝试:http://ideone.com/J1qD6m,只需在源代码上方按 fork 即可。
答案 2 :(得分:0)
对于线性时间,恒定空间算法:使用algorithm due to Misra and Gries查找出现在至少四分之一卡片边上的数字。最多有四个这样的候选人;至少有一半面朝上的牌上没有其他号码出现。对于每个候选人,确定需要翻转多少次。