简体   繁体   中英

Find missing numbers in array in O(log(n)) time

I'm given two arrays A and B where A is completely filled with positive integers and B is A with some constant number of elements turned into zeroes. I'm also given an arbitrary function that takes an array and gives the sum of the array in O(1) from an a to b where a and b are indices in the array.

I'm supposed to design an algorithm that turns array B into array A in O(log(n)) time, but I'm having difficulties seeing how that is possible.

I've come up with a solution that is O(n) where I simply compare the index of A to the index of B. If they are the same, I continue through the loop and if they are different, I update the value of B[i] to be A[i]. I don't see a way to improve this, especially if the arrays are unsorted.

Binary search for a zero'd element. (Hint: if sum(A, lo, hi) ≠ sum(B, lo, hi) then the range contains at least one zero'd element. If you have such a range, you can divide it on half: if the first half contains azero'd element continue with the first half, otherwise continue with the second half. Stop when you get to a one-element range.

Let's call the given function sum . As described, you would call it as sum(array, i, j) and it would return the sum of array[i] +... + array[j-1] . I assume the range excludes the index at j itself, but the reasoning is the same if it would be included.

Let's also call k the number of zeroes in B .

Now you can use a binary search to find the left-most 0 in B , by comparing sum(A, 0, i) with sum(B, 0, i) while varying i according to the binary search method. Then when the lowest index is found for which those sums are not equal, then you know B[i] is zero, and in O(logn) time.

So then assign the corresponding (non-zero) value from A[i] to B[i] . Then repeat this k times. Since k is constant, it does not influence the time complexity: O(klogn) is still O(logn) when k is constant, like for instance 2.

Here is an implementation in JavaScript with an example input, and k=2 .

 // Implementation of the hidden function, which (contrary to this implementation) // should run in constant time function sum(arr, i, j) { result = 0; while (i < j) { result += arr[i++]; } return result; } // example let a = [3,2,6,7,1,9,8,5]; let b = [3,2,0,7,1,9,0,5]; let n = a.length; let k = 2; for (let times = 0; times < k; times++) { // Apply binary search let low = 0; let high = n; while (low < high) { let mid = (low + high + 1) >> 1; if (sum(a, 0, mid) == sum(b, 0, mid)) { low = mid; } else { high = mid - 1; } } // Found index where zero is at: b[low] = a[low]; } console.log(b);

When k is not known

...then it is not constant, but variable. The time complexity then becomes O((k+1)logn) , which is O(klogn) , and the loop must keep going until a search no longer finds a zero (at the (k+1) th iteration):

 // Implementation of the hidden function, which (contrary to this implementation) // should run in constant time function sum(arr, i, j) { result = 0; while (i < j) { result += arr[i++]; } return result; } // example let a = [3,2,6,7,1,9,8,5]; let b = [3,2,0,7,1,9,0,5]; let n = a.length; // no definition of k here while (true) { let low = 0; let high = n; while (low < high) { let mid = (low + high + 1) >> 1; if (sum(a, 0, mid) == sum(b, 0, mid)) { low = mid; } else { high = mid - 1; } } if (low >= n) break; // no zero found // Found index where zero is at: b[low] = a[low]; } console.log(b);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM