我正在尝试解决this算法任务。当我提交我的代码时,在某些测试用例中,我的代码太慢了,而在我的代码中,我的代码输出错误。我试图找到我犯错的地方,但我真的无能为力。因为在我的代码失败的测试用例中,有更多的长度数组,我无法检查每个输出以找出错误。
所以我想知道你是否可以给我一些建议:
这是我的代码:
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int length = sc.nextInt();
int arr[] = new int[length];
for(int i=0; i<length; i++)
arr[i] = sc.nextInt();
int test = sc.nextInt();
int type, check;
for(int i=0; i<test; i++)
{
type = sc.nextInt();
check = sc.nextInt();
if(type == 0)
{
System.out.println(greaterOrEqualThan(arr, check, length));
}
else if(type == 1)
{
System.out.println(greaterThan(arr, check, length));
}
}
}
public static int greaterThan(int arr[],int x, int length)
{
int low = 0;
int high = length-1;
int mid;
while( low+1 < high)
{
mid = (high+low)/2;
if(arr[mid] <= x)
low = mid;
else if(arr[mid] > x)
high = mid;
}
int startIndex;
if(arr[low] > x && arr[low] != arr[high])
startIndex = low;
else if(arr[high] > x && arr[high] != arr[low])
startIndex = high;
else
return 0;
return length-startIndex;
}
public static int greaterOrEqualThan(int arr[], int x, int length)
{
int low = 0;
int high = length-1;
int mid;
while(low+1 < high)
{
mid = (low+high)/2;
if(arr[mid] < x)
low = mid;
else if(arr[mid] == x)
{
high = mid;
break;
}
else
high = mid;
}
int startIndex;
if(arr[low] >= x)
startIndex = low;
else if(arr[high] >= x)
startIndex = high;
else
return 0;
return length-(startIndex);
}
}
答案 0 :(得分:2)
我认为在阵列中存在多个目标值实例的情况下,您的一个或两个算法可能不正确。 (例如[1,3,3,3,5]
。
有三种情况需要考虑:
x
未在数组中出现x
恰好在数组中出现一次x
不止一次出现在数组中我建议对两种方法中的每种方法使用经典的二进制搜索算法(精确的二进制搜索算法,无需修改)。之后你所做的就是与众不同。
首先,运行经典的二进制搜索算法,直接内联到您的方法中(这样您就可以访问low
和high
的终端值。
其次,在二进制搜索终止后,测试array[mid] != x
。如果array[mid] != x
,那么数组中不会出现x
,而low == high + 1
(自high
和low
已经过了。{'}}数组中不小于x
的数字和数组中大于x
的数字都等于array.length - low
。
第三,如果array[mid] == x
为真,那么x
确实会在数组中出现一次或多次。由于经典的二进制搜索算法会在找到x
时立即终止,因此它终止于其中的“x
不确定”。
在这种情况下,为了找到不小于x
的数字计数,您必须使用以下代码段找到数组中的“第一个”x
:
do {
mid = mid - 1;
} while (array[mid] == x);
然后 mid
将成为中数组中“第一个”x
之前的元素的索引,因此数字的计数不小于{{1将是x
。
同样,为了找到大于array.length - mid + 1
的数字计数,您必须首先使用以下代码段找到数组中的“last”x
:
x
然后 do {
mid = mid + 1;
} while (array[mid] == x);
将成为数组中“最后一个”mid
之后的元素的索引,因此大于{{1}的数字的数量将是x
。
x
array.length - mid - 1
int low = 0;
int high = array.length - 1;
int mid = (high + low) / 2; // priming read
while (array[mid] != x && low <= high) {
if (array[mid] > x)
high = mid - 1;
else // (array[mid] < x)
low = mid + 1;
mid = (high - mid) / 2;
}