在迭代数组时检查某些“分隔元素”是否经常间隔?

时间:2015-04-19 16:57:50

标签: arrays algorithm language-agnostic iteration

我无法想出这个问题必须存在的高效算法:

遍历数组检查“标记”元素。如果我发现任何标记没有将其余元素划分为相同长度的运行,请设置一个标志。除了最后一轮,其余部分。

不应设置标志的示例:

*....*....*..*

应设置标志的示例:

*....*...*...*
*....*....**

Intuition说,应该可以在网上做一些非常简单的事情,这可能相当于一些众所周知的问题,而这个问题的名字我不知道。

2 个答案:

答案 0 :(得分:1)

<强>解决方案:

计算标记之间的元素数量并形成列表。然后检查这个列表元素是否全部相同,不包括最后一个元素,列表的最后一个元素不是0. 边缘情况:只有一个元素,它可以是0.

Python代码:

def is_correct(string):
    splitted_list = string.split("*")[1:-1]  # Split and strip edge elements.
    if len(splitted_list) == 1:
        return True
    if len(splitted_list[-1]) == 0:   # Check that last element is 0.
        return False
    for i in range(1, len(splitted_list)-1):   # Check that others are the same.
        if len(splitted_list[0]) != len(splitted_list[i]):
            return False
    return True  

# Test    
print is_correct("*....*....*..*")
print is_correct("*....*...*...*")
print is_correct("*....*....**")

答案 1 :(得分:1)

诀窍是首先根据第一次*xyz*次发生计算预期长度。一旦知道了这一点,我们知道剩下的分隔符(*)的位置。如果遇到分隔符不合适,除非它是剩余部分的一部分,否则它是非法的。

它与Riko的答案基本上是相同的逻辑,但是由于计算段大小是通过内联而不是使用string.split完成的,所以代码更多。

以下是JavaScript中的示例。我试图通过远离JavaScript的更多功能方面来尽可能简单地保持它。不幸的是,这使它成为一堵代码墙。

var isCorrect = function( str, divider ) {

    process.stdout.write( str + ': ' );

    // First check the obvious cases. These allow us to skip these checks
    // within the loop.
    if( str[0] !== divider )
        return "Doesn't start with divider";
    if( str[ str.length - 1 ] !== divider )
        return "Doesnt' end with divider";

    // Two variables to hold the state.
    // The second variable (divisions) is required only if we want to make
    // sure that the last segment is "optimal".
    var division = null;
    var divisions = 0;

    // First find the first divider.
    var i = 1;
    for( ; i < str.length; i++ ) {
        if( str[i] === divider ) {
            division = i;
            divisions++;
            break;
        }
    }

    // Now that we know the division length, make sure the dividers
    // are in expected positions.
    for( ; i < str.length; i++ ) {

        var expectedDivider = ( (i) % division === 0 );

        // See if we are expecting a divider.
        if( expectedDivider ) {
            if( str[i] !== divider )
                return "Expected divider at position " + i;
            divisions++;
            continue;
        }

        // Since we are not expecting a divider, make sure we don't have one.
        if( str[i] === divider ) {

            // We had a divider in an unexpected place. This is only allowed for
            // the last segment.
            if( i < str.length - 1 )
                return "Divider not expected at position " + i;

            // This is last segment. We could return 'ok' here unless we want
            // the optimal segments.

            // For optimal segments we want to know whether the last segment
            // could have "borrowed" items from the previous ones while still
            // remaining smaller than the rest.

            // Calculate the bits missing from the last segment.
            var offset = ( (i-1) % division );
            var missing = division - offset - 1;

            if( offset === 0 )
                return "Empty division at the end";

            // Could the missing bits be taken from the previous divisions?
            if( missing > divisions )
                return "Last division too short";

            // Last segment was OK.
            return "ok";
        }
    }

    // All divisions were in expected places:
    // Last segment was as long as the rest.
    return "ok";
};

我使用的测试用例:

// Simple cases

// OK
console.log( isCorrect( '*--*--*--*', '*' ) );
console.log( isCorrect( '*---*---*---*', '*' ) );
console.log( isCorrect( '*---*---*--*', '*' ) );

// Middle segment too short.
console.log( isCorrect( '*-----*----*-----*', '*' ) );

// First segment too short
console.log( isCorrect( '*----*-----*-----*', '*' ) );

// "Optimality" tests

// In "optimal" division the segments could be divided to three with
// *----*----*---* so *-----*-----*-* is "unoptimal"
console.log( isCorrect( '*-----*-----*-*', '*' ) );

// These are "optimal"
console.log( isCorrect( '*-----*-----*--*', '*' ) );
console.log( isCorrect( '*-----*-----*---*', '*' ) );
console.log( isCorrect( '*-----*-----*----*', '*' ) );
console.log( isCorrect( '*-----*-----*-----*', '*' ) );

// Last segment too long
console.log( isCorrect( '*-----*-----*------*', '*' ) );

// Last segment empty
console.log( isCorrect( '*--*--*--*--*--**', '*' ) );