算法 - LinkedIn编码回合

时间:2014-12-02 06:39:57

标签: arrays algorithm linkedin kadanes-algorithm

给出仅包含0和1的数组作为输入。您可以选择数组i和j的任意两个索引并翻转它们之间的所有元素(即0-> 1和1-> 0)。找到翻转后可以获得的数组的最大总和。              例如:对于[0,1,0,0,1,0],答案是4.(从索引2翻到3)。

这是我的方法:
 1)找到数组中所有索引的前缀sum(保持sum [i])                      2)翻转原始数组中的所有位                      3)使用Kadane的算法找到最大子阵列和MAXSUM。让max子阵列的起始和结束索引为i和j。
                     4)答案是sum(i-1)+ MAXSUM + sum(n-1)-sum(j)。

请告诉我我的方法是否正确。

1 个答案:

答案 0 :(得分:2)

实际上,您可以通过阵列一次性轻松地完成此操作。您可以跟踪当前翻转位的范围有多好。只要您处于正数,当前范围就可以预先设置到任何后续范围。但是一旦你达到零或负,你应该放弃你的范围并开始新的范围。

例如,如果您发现翻转指数0..5会产生+4,那么这很好,您可能希望将0..5作为范围的一部分,因为如果您也是要翻转指数6..X。但是如果0..5导致-1,你想不使用0..5因为这只会降低你的分数。那么在那时你将从6点开始。也许它在代码中更容易看到。这是一个C版本,可以一次解决问题:

// Returns best range (start..end) to flip, and best score achieved.
static void findRange(const int *array, int *pStart, int *pEnd, int *pScore)
{
    int start     = 0;
    int best      = 0;
    int i         = 0;
    int diff      = 0;
    int base      = 0;
    int bestStart = -1;
    int bestEnd   = -1;

    // Count the number of 1s in the array already.
    for (i=0;i<N;i++)
        base += array[i];

    // Run through the array, keeping track of "diff", which is how much
    // we have gained by flipping the bits from "start" to "i".
    for (i=start=0;i<N;i++) {
        // Flip the number at i.
        if (array[i] == 0)
            diff++;
        else
            diff--;
        // If this range (from start to i) is the best so far, remember it.
        if (diff > best) {
            bestStart = start;
            bestEnd   = i;
            best      = diff;
        }
        // If we get to a zero or negative difference, start over with a
        // new range starting from i+1.
        if (diff <= 0) {
            start = i+1;
            diff  = 0;
        }
    }
    *pStart = bestStart;
    *pEnd   = bestEnd;
    *pScore = base + best;
}

编辑:在阅读了关于Kadane的算法之后,事实证明我写的内容是等效的,使用Kadane在修改过的数组上找到最大子数组,在这个数组中将每个0切换为1,每个1切换为-1