【问题标题】:Codility EvenSums GameCodility EvenSums 游戏
【发布时间】:2016-04-21 23:43:51
【问题描述】:

我正在努力完成编码挑战以提高我的编程技能。挑战详情为here
我也会把问题陈述复制到这里。

求和是两个玩家的游戏。给玩家一个 N 的序列 正整数,轮流交替。在每一回合,一名玩家 选择一个非空切片(连续元素的子序列),例如 该切片中的值之和为偶数,然后删除该切片 并连接序列的其余部分。第一位选手 谁不能合法走棋,谁就输了。

你和你的对手玩这个游戏,你想知道你是否 可以赢,假设你和你的对手都发挥最佳。你挪开 首先。

写一个函数:

字符串解(向量&A);

给定一个由 N 个整数组成的零索引数组 A,返回一个 格式为 "X,Y" 的字符串,其中 X 和 Y 分别是第一个和 您应该删除的切片的最后位置(包括) 假设你有一个获胜的策略,首先要取胜。如果 有不止一个这样的获胜切片,函数应该返回 X 值最小的那个。如果有多个切片 对于 X 的最小值,该函数应该返回最短的值。 如果您没有获胜策略,该函数应返回“NO 解决方案”。

例如,给定以下数组:

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]。 然后对手将能够删除第一个元素(甚至 sum 4) 或最后一个元素(偶数 2 的)。之后你可以制作一个 使数组仅包含 [7] 的移动,因此您的对手将 没有合法的举动,会输。可能的游戏之一显示在 下图:

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

对于以下数组:

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),超出输入存储(不计算存储 需要输入参数)。输入数组的元素可以是 修改。

首先我对问题陈述有一个误解,为什么在给定的示例中,第一个玩家在第一步中不能将 4 作为偶数范围,所以该函数应该返回 0,0 而不是 1,2。


第二个我解决问题的想法是计算输入数组中偶数范围的数量,如果计数是偶数,那么玩家一个赢了,我应该找到玩家可以采取的第一个偶数范围。

但我无法在规定的时间内解决,无法再次参加考试。

这是我尝试的代码:

    string solution(vector<int> &A) {
    int num_even_ranges = 0;
    int sum = 0;
    for (int i = 0; i < A.size(); i++)
    {
        sum += (A[i]%2);
        if (sum % 2 == 0 || A[i]%2 == 0)
        {
            num_even_ranges++;
            sum = 0;
        }
    }
    if (num_even_ranges % 2 == 0)
        return "NO SOLUTION";
    sum = 0;
    int start = 0;
    for (int i = start; i < A.size(); i++)
    {
        sum += A[i];
        if (sum % 2 == 0 && i > start)
        {
            return to_string(start) + "," + to_string(i);
        }

        if (i + 1 < A.size())
        {
            if (A[i] % 2 == 0 && A[i+1] % 2 == 1)
            {
                sum = 0;
                start = i + 1;
            }
        }
    }
}


如果不是这个有趣问题的正确解决方案,我对问题的解决方案是否正确。

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    关于你的第一个问题,如果第一个玩家拿了 4 (0,0),剩下的数组是:5,3,7,2。然后对手可以拿走 3,7,2,第一个玩家会输,因为剩下的 5 是奇数。所以这不是有效的解决方案。

    【讨论】:

    • 我同意玩家在任何情况下都必须获胜。
    【解决方案2】:

    我得到了 Javascript 的解决方案,请参考下面的代码

    Javascript 代码:

    function len(obj){
    if(obj instanceof Array || typeof obj === "string")
        return obj.length;
    else {
        var count = 0;
        for(var i in obj){
            if(obj.hasOwnProperty(i))
            count++;
        }
        return count;
    }
    }
    
    function check(start, end) {
    if (start > end) {
        res = 'NO SOLUTION';
    }
    else {
        res = start.toString() + ',' + end.toString();
    }
    
    return res;
    }
    
    function trans(strr){
    if (strr =='NO SOLUTION') {
        return [1, -1]
    }
    else {
       a = strr.split(',');
    }
    
    return [parseInt(a[0]), parseInt(a[1])];
    }
    
    function solution(A){
    odd_list = [];
    for(var ind=0; ind<A.length; ind++)
    {
        if(A[ind]%2==1) {
            odd_list.push(parseInt(ind));    
        }
    }
    
    if (len(odd_list)%2 == 0) {
        return check(0, len(A) - 1);
    }
    
     tempList = odd_list;
     odd_list = [];
    
     odd_list.push(-1);
    
     for(var i=0; i< tempList.length; i++) {
         odd_list.push(tempList[i]);
     }
    
     odd_list.push(len(A));
    
     var res_cand = [];
     count = odd_list[1];
     second_count = len(A) - 1 - odd_list[odd_list.length-2];
     first_count = odd_list[2]- odd_list[1] - 1;
    
     if (second_count >= count) {
        res_cand.push(trans(check(odd_list[1] + 1 , len(A) - 1 - count ))); 
     }
    
     if (first_count >= count) {
        res_cand.push(trans(check(odd_list[1] + count + 1, len(A) - 1))) 
     }
    
    twosum = first_count + second_count;
    
    if (second_count < count && count <= twosum) {
        res_cand.push(trans(check(odd_list[1] + (first_count - (count -     second_count )) + 1, odd_list[odd_list.length-2] )));
    }
    
    count = len(A) - 1 - odd_list[odd_list.length-2];
    first_count = odd_list[1];
    second_count = odd_list[odd_list.length-2] - odd_list[odd_list.length-3] - 1;
    
    if(first_count >= count) {
        res_cand.push(trans(check( count, odd_list[odd_list.length-2] - 1 )));
    }
    
    if (second_count >= count) {
        res_cand.push(trans(check( 0, odd_list[odd_list.length-2] - count - 1)))
    }
    
    twosum = first_count + second_count;
    
    if(second_count < count && count <= twosum) {
        res_cand.push(trans(check(count-second_count, odd_list[odd_list.length-3])))
    }
    
    cur = [-1, -2];
    
    res_cand =  res_cand.sort(sortFunction);
    
    for(var i= res_cand.length-1 ; i >= 0 ; i--) {
          var row = res_cand[i]; 
          if(row[0] !== -1) {
            cur = row;  
          }
    }
    
    return check(cur[0], cur[1]);
    }
    
    function sortFunction(a, b) {
    if (a[0] === b[0]) {
        return 0;
    }
    else {
        return (a[0] < b[0]) ? -1 : 1;
    }
    }
    

    你可以在下面的小提琴链接中得到答案

    https://jsfiddle.net/3ed1kuoj/

    【讨论】:

      【解决方案3】:

      move(0,0) 是有效的,因为在每一回合中,玩家只能使用和为偶数的子序列进行移动。

      “在每一回合中,玩家选择一个非空切片( 连续元素),使得该切片中的值之和为 甚至”

      注意:每次移动后,我们只考虑剩余序列的操作/移动

      After player1's first move(0,0), the remaining sequence will be [5,3,7,2],
      then player2's first move(0,1), the remaining sequence will be [7,2],
      then player1's second move(1,0), the remaining sequence will be [7]
      Now player 2 is unable to make any legal move! So player 1 win's 
      

      因此这是一个制胜策略!

      【讨论】:

        猜你喜欢
        • 2015-06-12
        • 2014-04-08
        • 2014-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多