我正在尝试改进算法的运行时间,该算法计算输入数组中的总数0。输入数组的长度为n,由0和1组成,按排序顺序排列。
到目前为止我的算法是:
Algorithm : zeroCount(A)
Input : An sorted array A containing 0s and 1s
Output : total number of 0s in A
if A[0]=1 then
return 0;
len <— A.length
if A[len-1]=0 then
return len
count <— 0
i <—0
for i<len do
if A[i]==0 then
count++
i++
return count
Java实现是:
public int zeroCount(int[] a){
if(a[0]==1)
return 0;
int length =a.length;
if(a[length-1]==0)
return length;
int count=0;
for(int i=0;i<length&&a[i]==0;i++){
count++;
}
return count;
}
但是,运行时间是O(n)。任何改善此算法运行时间的建议都将受到赞赏。
答案 0 :(得分:9)
由于输入数组已经排序,因此您可以使用二进制搜索来获得更好的性能。这将运行时间改善为O(log n)。
使用二进制搜索的算法是:
Algorithm : zeroCount(A)
Input : sorted array A containing 0s and 1s
Output : total number of 0s in A
if A[0]=1 then
return 0;
len <— A.length
if A[len-1]=0 then
return len
return count(A,0,length)
Algorithm : count(A,lower,upper)
Input : sorted array A , integers lower and upper
Output : total number of 0s in A
mid <— (lower+upper) / 2
if A[mid] != A[mid-1] then
return mid
if A[mid] != A[mid+1] then
return mid+1
if A[mid] = 1 then
return count(A,lower,mid-1)
if A[mid] = 0 then
return count(A,mid+1,upper)
Java实现:
public int zeroCount(int[] a) {
if (a[0] == 1) // all are 1
return 0;
int length = a.length;
if (a[length - 1] == 0) //all are 0
return length;
return count(a, 0, length);
}
public int count(int[] a, int lower, int upper) {
int mid = (lower + upper) / 2;
if (a[mid] != a[mid - 1])
return mid;
if (a[mid] != a[mid + 1])
return mid + 1;
if (a[mid] == 1) { // all are 1 above mid
return count(a, lower, mid - 1);
} else if (a[mid] == 0) { // all are 0 below mid
return count(a, mid + 1, upper);
}
return 0;
}
答案 1 :(得分:3)
您可以调整二进制搜索,以查找数组中最后一次出现(例如,索引i)0。那么0的计数将是(i + 1)。
int CountOfZeroes(int[] A, int key)
{
int low = 0;
int high = A.size - 1;
int result = -1;
while (low <= high)
{
int mid = low + (high-low)/2;
if (A[mid] == key)
{
result = mid;
low = mid + 1;
}
else if (key < A[mid])
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
return result + 1;
}
您将在键设置为0的情况下调用上述函数。时间复杂度为O(log n)
。