以下是问题:
一个字符串包含几个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。为什么呢?
答案 0 :(得分:1)
您的二进制搜索算法错误。您可以在维基百科上找到规范的二进制搜索算法,因此我不会将其提供给您或链接到它。
但是,您不能仅使用两个索引min
和max
来实现二进制搜索。您必须在单独的变量中计算中点,然后使用该(中点)位置的探测结果来确定要移动的端点。
答案 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