一种方法,它接收一个未排序的数组,该数组由相邻的相等数对和一个没有对的数对组成。例如-
int [] a = {6,6,18,18,-4,-4,12,9,9};
int [] c = {8,-7,-7,3,3,0,0,10,10,5,5,4,4};
代码必须返回索引和数字本身。
现在的问题是关于时间复杂性,我知道o(logn)可以解决这个问题,但我的代码有一半是有效的:
public static int findSingle (int [] a) {
int high = a.length-1;
int low = 0;
int mid = 0;
int found = 0;
mid = ((high-low)/2);
while (mid >= 1) {
if (a[mid] != a[mid-1])
low = mid +1;
mid =((high - low)/2);
if (mid == 1)
found = a[mid];
if (a[mid] == a[mid-1])
high = mid-1;
mid = ((high - low)/2);
}
return found;
}
现在给出这个数组:
int [] d = {8,8,-7,3,3,0,0,10,10,5,5,4,4};
它说数字在第8个元素中,这显然不是真的,在某些数组中它也会出错。有什么问题吗?
编辑:我注意到我应该将“mid”指定为high+low/2,但这两种方法都不能解决问题。
1条答案
按热度按时间c6ubokkw1#
你在正确的轨道上,但是你的代码有一些问题。
为什么mid小于或等于1是退出条件?您希望退出条件是在找到值时,该值可以位于数组中的任何位置,而不仅仅是在开始时。我要把退出条件改为
high
以及low
,就像在普通的二进制搜索中一样。首先,这个公式找不到中间的数字
high
以及low
. 这应该是((high+low)/2)
. 此外,这些列表的性质使得保持数据的奇偶性非常重要mid
始终如一。我要确保mid
通过添加mid += mid%2;
什么时候mid
已设置。再次强调的是
high
以及low
是非常重要的。两者应始终保持平衡。我们知道这一点mid
是平的,所以high
以及low
不应被抵消mid
以+/-1。这是代码中最大的问题。首先,您是要查找单个数字的索引还是单个数字的值?你说你在找索引,但你的代码却在找
a[mid]
这是一个值。我下面的代码找到了索引,但这很容易修改。第二,你只有在mid
是1。这意味着您的代码将始终返回0或0a[1]
.还有几张便条。没有理由设置
mid
每个循环两次,并检查两次a[mid] != a[mid-1]
以及a[mid] == a[mid-1]
. 相反,每个循环设置一次mid,检查其中一个条件,然后使用if/else
. 而且,没有理由使用found
. 相反,只要使用high
或者low
当循环退出时,现在它正正确退出。最终代码:
我还没有完全测试过这个,但是从我看到的几个测试用例来看,它似乎是有效的。
编辑:
原来有个虫子(谢谢亚历克斯·鲁登科)。固定版本: