卡的最小翻转

时间:2014-02-01 10:32:49

标签: algorithm

我有N张牌,前面和后面都写有数字。现在,我可以翻转任何一张牌,使其底部成为顶部。

考虑到卡片顶部和底部的数字,我需要找到最少的移动次数,这些移动可以使至少一半的卡片在其顶部显示相同的数字。

如果无法这样做,那么也要告诉它是不可能的。

示例:假设我们有3张牌并表示为(顶部的数字,底部的数字)

卡1:(3,10)

卡2:(10,3)

卡3:(5,4)

现在,这里的minmum移动只有1,因为我们可以翻转第一张牌,使得顶部的数字变为10.由于三张牌中的两张在他们的顶部有相同的数字(10),我们不需要改变任何东西否则,答案是1。

3 个答案:

答案 0 :(得分:1)

从您的问题来看,以下几点并不完全清楚:

  • 我假设您拥有完整的信息,即您从一开始就知道 每张卡片底部的内容;

我会选择以下内容:

  • 让N =卡数;
  • 对于卡片上显示的每个号码i,计算出现的卡片的m(i)数量(顶部或底部);
  • 如果没有m(i)大于N/2则失败
  • 对于显示在电话线上的每个号码i,请计算卡片中top(i)的数量,如果它出现在顶部;
  • 计算c m(c) - top(c)最小的数字;
  • 翻转m(c) - top(c)c位于底部,但不在顶部。

答案 1 :(得分:0)

  1. N是卡的数量。
  2. top(v)计算v在v=0..N-1
  3. 上显示的频率
  4. bottom(v)计算v出现在底部的频率。
  5. 根据值在top(v)
  6. 上显示的频率对值进行排序
  7. 选择v
  8. 最大的值top(v)
  9. 如果top(v)+bottom(v) >= N/2 v是你的结果,否则从排序列表中选择下一个
  10. 这是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查找出现在至少四分之一卡片边上的数字。最多有四个这样的候选人;至少有一半面朝上的牌上没有其他号码出现。对于每个候选人,确定需要翻转多少次。