Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 最小翻牌次数_Algorithm - Fatal编程技术网

Algorithm 最小翻牌次数

Algorithm 最小翻牌次数,algorithm,Algorithm,我有N张正面和背面都写有数字的扑克牌。现在我可以一次翻转任何一张牌,使其底部变成顶部 给定纸牌顶部和底部的数字,我需要找到至少一半纸牌顶部显示相同数字的最小移动次数 如果不可能这样做,那么也说明不可能 示例:假设我们有3张卡,表示为(顶部数字,底部数字) 卡1:(3,10) 卡片2:(10,3) 卡片3:(5,4) 现在,这里的最小移动量只有1,因为我们可以翻转第一张牌,使顶部的数字变成10。由于三张卡片中的两张在其顶部(10)有相同的编号,因此我们不需要更改任何其他内容,因此答案为1。您的问题

我有N张正面和背面都写有数字的扑克牌。现在我可以一次翻转任何一张牌,使其底部变成顶部

给定纸牌顶部和底部的数字,我需要找到至少一半纸牌顶部显示相同数字的最小移动次数

如果不可能这样做,那么也说明不可能

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

卡1:(3,10)

卡片2:(10,3)

卡片3:(5,4)


现在,这里的最小移动量只有1,因为我们可以翻转第一张牌,使顶部的数字变成10。由于三张卡片中的两张在其顶部(10)有相同的编号,因此我们不需要更改任何其他内容,因此答案为1。

您的问题并不完全清楚以下几点:

  • 我假设你有完整的信息,即你从一开始就知道每张卡片的顶部和底部是什么
我将采取以下措施:

  • 设N=卡片数量
  • 对于卡片上出现的每个编号
    i
    ,计算卡片上出现的编号
    m(i)
    (顶部或底部)
  • 如果无
    m(i)
    大于
    N/2
    则失败
  • 对于电线上出现的每个编号
    i
    ,计算卡的编号
    top(i)
    ,其中if出现在顶部
  • 计算
    c
    其中
    m(c)-top(c)
    最小的数字
  • 翻转
    m(c)-top(c)
    ,使
    c
    位于底部,而不是顶部
  • N
    是卡的数量
  • top(v)
    计算v出现在顶部的频率,
    v=0..N-1
  • bottom(v)
    计算v在底部出现的频率
  • 根据值出现在顶部的频率对值进行排序,
    top(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,可以在此处尝试:,只需在源代码上方按fork键。

    对于线性时间、常量空间算法:使用查找至少四分之一卡片侧面上显示的数字。这样的候选人最多有四名;至少一半正面朝上的卡片上不能出现其他号码。对于每个候选人,确定需要翻转多少次。

    一张牌的两面数字可能相同吗?@hivert是的。它们可能是相同的。你不认为这两张牌的两面数字不同吗?@Bartlomiej Lewandowski:不,我没有,因为我数的是牌的数量,而不是面的数量。在第二点中,如果它出现在两张脸上,则只对一张脸有效。