Interview Question
Software Engineer / DevelopersCountry: United States
Interview Type: Written Test
Not sure why a divide and conquer approach would be requested- the problem can be solved easily enough in a linear fashion with O(n) complexity and O(1) memory:
public static int countConsecutive0s(int[] arr){
int counter = 0;
for(int i = 1; i < arr.length; i++){
if(arr[i-1] == 0 && arr[i] == 0){
counter++;
}
}
return counter;
}
However, if you had to do a divide and conquer approach specifically like if you were doing some GPU work, then you could do it like the following (pseudo coded up from the perspective of each core)
linearly count consecutive 0s in assigned section
if(not the first section in the array)
if(section starts with 0 and previous section ends with 0){
add 1 to count
}
}
save the counts to a working buffer
use logarithmic compression to sum all the counts from the different cores
Runtime complexity will by O(n / c + c log c) where c is the number of cores and memory is O(c)
You just need to use a binary search over the array looking for zeros. Whenever it finds one, just check whether the element to the right is also a zero.
Note however that you do not gain anything by using divide and conquer in this problem. It may incur additional cost even, since the DaC paradigm brings in more space complexity due to the call stack.
An implementation in C:
int count(const int *V, int s, int e, int n)
{
if (e < s) return 0;
int counter = 0;
int mid_idx = (s+e)/2;
if (V[mid_idx] == 0) {
if (mid_idx < n && V[mid_idx+1] == 0) {
++counter;
}
}
return counter + count(V, s, mid_idx-1, n) +
count(V, mid_idx+1, e, n);
}
int main(int argc, char *argv[])
{
int V[] = {3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2};
int n = sizeof(V)/sizeof(int);
printf("%d\n", count(V, 0, n-1, n-1));
return 0;
}
Why can't we forward and backward linear search simultaneously. When we the center break the loop.
#include <iostream>
#include <cstdio>
using namespace std;
int across(int arr[], int mid, int l, int h) {
int count = 0;
if (arr[mid] == 0) {
if (mid - 1 >= l && arr[mid - 1] == 0) {
count++;
}
if (mid + 1 <= h && arr[mid + 1] == 0) {
count++;
}
}
return count;
}
int countConsec(int arr[], int l, int h) {
if (l > h) {
return 0;
}
int mid = (l + h) / 2;
int count;
int a = countConsec(arr, l, mid - 1);
int b = countConsec(arr, mid + 1, h);
int c = across(arr, mid, l, h);
count = a + b + c;
return count;
}
int main() {
int arr[] = {3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2};
cout << countConsec(arr, 0, 12) << endl;
return 0;
}
- naren November 17, 2014