算法背后的逻辑是什么

时间:2016-07-28 02:36:06

标签: algorithm python-2.7

我正在努力解决codility的问题

  

“偶数总和”

但我无法这样做。以下是问题。

甚至总和也是两个玩家的游戏。给予玩家一系列N个正整数并轮流轮流。在每个回合中,玩家选择非空切片(连续元素的子序列),使得该切片中的值的总和是偶数,然后移除切片并连接序列的其余部分。第一个无法进行合法行动的玩家将失去游戏。

你扮演这个游戏对抗你的对手,你想知道你是否能够获胜,假设你和你的对手都发挥得最好。你先移动。

写一个函数:

string solution(vector< int>& A);

给定由N个整数组成的零索引数组A,返回格式为“X,Y”的字符串,其中X和Y分别是您应该删除的切片的第一个和最后一个位置(包括)假设你有一个成功的策略,在你的第一步中获胜。如果存在多个这样的获胜切片,则该函数应该返回具有最小值X的那个。如果存在多个具有最小值X的切片,则该函数应该返回最短的。如果您没有获胜策略,该功能应返回“NO SOLUTION”。

例如,给定以下数组:

  

A [0] = 4 A [1] = 5 A [2] = 3 A [3] = 7 A [4] = 2

该函数应返回“1,2”。在从位置1到2移除切片(具有5 + 3 = 8的偶数和)之后,剩余的阵列是[4,7,2]。然后对手将能够移除第一个元素(偶数为4)或最后一个元素(偶数为2)。之后你可以做一个只包含[7]的数组的移动,这样你的对手就不会有合法的举动而会输掉。其中一个可能的游戏显示在following picture

请注意,删除切片“2,3”(偶数为3 + 7 = 10)也是一个获胜的动作,但切片“1,2”的值较小。

对于以下数组:

  

A [0] = 2 A [1] = 5 A [2] = 4

该功能应返回“NO SOLUTION”,因为没有策略可以保证您获胜。

假设:

N是[1..100,000]范围内的整数;数组A的每个元素是[1..1,000,000,000]范围内的整数。复杂度:

预期的最坏情况时间复杂度为O(N);预期的最坏情况空间复杂度是O(N),超出输入存储(不计入输入参数所需的存储)。可以修改输入数组的元素。 我在python中找到了一个在线解决方案。

def check(start, end):
    if start>end:
        res = 'NO SOLUTION'
    else:
        res = str(start) + ',' + str(end)

    return res

def trans( strr ):
    if strr =='NO SOLUTION':
        return (-1, -1)
    else:
        a, b = strr.split(',')
        return ( int(a), int(b) )


def solution(A):
    # write your code in Python 2.7

    odd_list = [ ind for ind in range(len(A)) if A[ind]%2==1 ] 

    if len(odd_list)%2==0:
        return check(0, len(A)-1)


    odd_list = [-1] + odd_list + [len(A)]
    res_cand = []
    # the numbers at the either end of A are even
    count = odd_list[1]
    second_count = len(A)-1-odd_list[-2]
    first_count = odd_list[2]-odd_list[1]-1
    if second_count >= count:
        res_cand.append(  trans(check( odd_list[1]+1, len(A)-1-count )))

    if first_count >= count:
        res_cand.append(  trans(check( odd_list[1]+count+1, len(A)-1 )))  

    twosum = first_count + second_count
    if second_count < count <= twosum:
        res_cand.append(  trans(check( odd_list[1]+(first_count-(count-second_count))+1, odd_list[-2] )))

    ###########################################
    count = len(A)-1-odd_list[-2]
    first_count = odd_list[1]
    second_count = odd_list[-2]-odd_list[-3]-1
    if first_count >= count:
        res_cand.append(  trans(check( count, odd_list[-2]-1 )))

    if second_count >= count:
        res_cand.append(  trans(check( 0, odd_list[-2]-count-1)) )

    twosum = first_count + second_count
    if second_count < count <= twosum:
        res_cand.append(  trans(check( count-second_count, odd_list[-3])) )



    res_cand = sorted( res_cand, key=lambda x: (-x[0],-x[1]) )

    cur = (-1, -2)
    for item in res_cand:
        if item[0]!=-1:
            cur = item

    return check( cur[0], cur[1] )

此代码有效,我无法理解另一个函数的代码和流程。但是我不明白算法的逻辑。它如何解决问题并解决了问题。这可能是一项漫长的任务,但任何人都可以非常关心我的算法。提前谢谢。

1 个答案:

答案 0 :(得分:0)

到目前为止,我已经发现奇数的数量对于找出结果至关重要。特别是需要第一个奇数和最后一个奇数的索引来计算重要值。

现在我需要了解比较背后的逻辑,例如“if first_count&gt; = count”以及“second_count&lt; count&lt; = twosum”。

更新: 嘿伙计们,我找到了问题的解决方案,最后理解了算法的逻辑。

这个想法背后是阵列的对称性。如果阵列是对称的,我们永远不会赢得比赛。这里对称被定义为这样一个数组,其中中间只有一个奇数,而在那个奇数的两边都有相等数量的均匀。

如果赔率甚至可以直接赢得比赛。

如果存在奇数个赔率,我们应该总是尝试使阵列对称。这就是算法正在尝试做的事情。

现在有两种情况。最后一个奇数将保留或第一个奇数将保留。如果你们不理解,我会很乐意解释更多。感谢。