二进制搜索错误的位置?

时间:2017-02-26 21:12:39

标签: java

以下是问题:

一个字符串包含几个X,后跟几个O.设计一个分而治之的算法,在log 2 (n)步骤中找到字符串中X的数量,其中n是字符串的长度。

这是我的代码:

public static int count(String str){
    int min = 0;
    int max = str.length() - 1;
    while(min < max){
        if(str.charAt(min) == 'X')
            min += (max - min) / 2; 
        else
            max = min + (max - min) / 2;
    }
    return min;
}

它似乎在大部分时间都有效,但在某些情况下会产生意外的输出。例如,当我把它给它字符串“XXXXOOOO”它应该返回4,但它返回5。为什么呢?

2 个答案:

答案 0 :(得分:1)

您的二进制搜索算法错误。您可以在维基百科上找到规范的二进制搜索算法,因此我不会将其提供给您或链接到它。

但是,您不能仅使用两个索引minmax来实现二进制搜索。您必须在单独的变量中计算中点,然后使用该(中点)位置的探测结果来确定要移动的端点。

答案 1 :(得分:1)

这种二进制搜索在每次迭代时重复地将字符串的大小分成大约一半。中间是在每次迭代时计算的。如果中间索引中的项目为“X”,则搜索中间右侧的字符串。如果中间索引中的项目为“O”,则搜索中间左侧的字符串。这将继续,直到列表中只剩下一个元素。如果此元素为“X”,则单元素列表位于最后一个X的索引处,因此返回索引+ 1。否则,最后一个X是少一个元素。

    public static int countX(String xos) {
        int start = 0;
        int end = xos.length() -1;

        int middle = start + (end-start)/2;
        while (start < end) {
            if (xos.charAt(middle) == 'X') {
                start = middle+1;
            } else {
                end = middle-1;
            }
            middle = start + (end-start)/2;
        }
        return xos.charAt(start)=='X'?start+1:start;
    }

测试功能:

public static void main(String[] args)
{
    Random r = new Random();

    // Generate 25 strings
    for (int tries = 0; tries < 25; tries++ ) {
        // Generate a random length
        int stringLength = r.nextInt(75)+1;
        // Generate a random number of Xs
        int numX = r.nextInt(stringLength+1);
        StringBuilder sb = new StringBuilder(stringLength);

        // add random number of Xs to the string
        for (int i=0; i<numX; i++) {
            sb.append("X");
        }
        // add Os to make up the length
        for (int i=numX; i<stringLength; i++) {
            sb.append("O");
        }
        // Convert StringBuilder to String
        String result = sb.toString();
        // Test function with the random string
        int countBin = countX(result);

        // Print results of test
        System.out.println(result + " (" + numX + " Xs, " + (stringLength-numX) + " Os) : " + countBin  + ", " +
            (countBin==numX?"Correct":"Incorrect"));
    }

示例输出:

XXXXXXXXXXXXXXOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO (14 Xs, 43 Os) : 14, Correct
XXXXXX (6 Xs, 0 Os) : 6, Correct
XXXOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO (3 Xs, 35 Os) : 3, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOOO (60 Xs, 3 Os) : 60, Correct
XXXXXXXXXXXXXXXXXXX (19 Xs, 0 Os) : 19, Correct
XXXXOOOOOOOOOOOOOOOOO (4 Xs, 17 Os) : 4, Correct
XO (1 Xs, 1 Os) : 1, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOOOOOOOOOOOOOOOOOO (28 Xs, 23 Os) : 28, Correct
XXOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO (2 Xs, 32 Os) : 2, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOO (55 Xs, 2 Os) : 55, Correct
XXXXXXXOOOOOOOOOOOOOOOOOOOOOOOO (7 Xs, 24 Os) : 7, Correct
XXXXXXXXXXOOOOO (10 Xs, 5 Os) : 10, Correct
XXXXXXXXXXXOOOOOOOOOOOOOOOOO (11 Xs, 17 Os) : 11, Correct
XXXXXXXXXXXOOOOOO (11 Xs, 6 Os) : 11, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOOOOOOOOOOOOOOOOO (30 Xs, 22 Os) : 30, Correct
XOOOOO (1 Xs, 5 Os) : 1, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOOOOOOO (63 Xs, 12 Os) : 63, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO (27 Xs, 32 Os) : 27, Correct
XXXXXXXXXXXXXOOOOOOOOOOOOOOOOOO (13 Xs, 18 Os) : 13, Correct
XXXO (3 Xs, 1 Os) : 3, Correct
XXXXXXXXOOOOOOOOOOOOO (8 Xs, 13 Os) : 8, Correct
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOOOOOOOOOOOOOOOOOOOOOOO (44 Xs, 28 Os) : 44, Correct
XOOOOOOOO (1 Xs, 8 Os) : 1, Correct
XXXXXXXXXXXXXXOOOOOOOOOOOOOOOO (14 Xs, 16 Os) : 14, Correct
XXXXXXXXXXXXXXXXOOOOOO (16 Xs, 6 Os) : 16, Correct