Efficient way to search an element - c

Recently I had an interview, where they asked me a "searching" question.
The question was:
Assume there is an array of (positive) integers, of which each element is either +1 or -1 compared to its adjacent elements.
Example:
array = [4,5,6,5,4,3,2,3,4,5,6,7,8];
Now search for 7 and return its position.
I gave this answer:
Store the values in a temporary array, sort them, and then apply binary search.
If the element is found, return its position in the temporary array.
(If the number is occurring twice then return its first occurrence)
But, they didn't seem to be satisfied with this answer.
What is the right answer?

You can do a linear search with steps that are often greater than 1. The crucial observation is that if e.g. array[i] == 4 and 7 hasn't yet appeared then the next candidate for 7 is at index i+3. Use a while loop which repeatedly goes directly to the next viable candidate.
Here is an implementation, slightly generalized. It finds the first occurrence of k in the array (subject to the +=1 restriction) or -1 if it doesn't occur:
#include <stdio.h>
#include <stdlib.h>
int first_occurence(int k, int array[], int n);
int main(void){
int a[] = {4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};
printf("7 first occurs at index %d\n",first_occurence(7,a,15));
printf("but 9 first \"occurs\" at index %d\n",first_occurence(9,a,15));
return 0;
}
int first_occurence(int k, int array[], int n){
int i = 0;
while(i < n){
if(array[i] == k) return i;
i += abs(k-array[i]);
}
return -1;
}
output:
7 first occurs at index 11
but 9 first "occurs" at index -1

Your approach is too complicated. You don't need to examine every array element. The first value is 4, so 7 is at least 7-4 elements away, and you can skip those.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int array[] = {4,5,6,5,4,3,2,3,4,5,6,7,8};
int len = sizeof array / sizeof array[0];
int i = 0;
int steps = 0;
while (i < len && array[i] != 7) {
i += abs(7 - array[i]);
steps++;
}
printf("Steps %d, index %d\n", steps, i);
return 0;
}
Program output:
Steps 4, index 11
Edit: improved after comments from #Martin Zabel.

A variation of the conventional linear search could be a good way to go. Let us pick an element say array[i] = 2. Now, array[i + 1] will either be 1 or 3 (odd), array[i + 2] will be (positive integers only) 2 or 4 (even number).
On continuing like this, a pattern is observable - array[i + 2*n] will hold even numbers and so all these indices can be ignored.
Also, we can see that
array[i + 3] = 1 or 3 or 5
array[i + 5] = 1 or 3 or 5 or 7
so, index i + 5 should be checked next and a while loop can be used to determine the next index to check, depending on the value found at index i + 5.
While, this has complexity O(n) (linear time in terms of asymptotic complexity), it is better than a normal linear search in practical terms as all the indices are not visited.
Obviously, all this will be reversed if array[i] (our starting point) was odd.

The approach presented by John Coleman is what the interviewer was hoping for, in all probability.
If you are willing to go quite a bit more complicated, you can increase expected skip length:
Call the target value k. Start with the first element's value v at position p and call the difference k-v dv with absolute value av. To speed negative searches, have a peek at the last element as the other value u at position o: if dv×du is negative, k is present (if any occurrence of k is acceptable, you may narrow down the index range here the way binary search does). If av+au is greater than the length of the array, k is absent. (If dv×du is zero, v or u equals k.)
Omitting index validity: Probe the ("next") position where the sequence might return to v with k in the middle: o = p + 2*av.
If dv×du is negative, find k (recursively?) from p+av to o-au;
if it is zero, u equals k at o.
If du equals dv and the value in the middle isn't k, or au exceeds av,
or you fail to find k from p+av to o-au,
let p=o; dv=du; av=au; and keep probing.
(For a full flash-back to '60ies texts, view with Courier. My "1st 2nd thought" was to use o = p + 2*av - 1, which precludes du equals dv.)

STEP 1
Start with the first element and check if it's 7. Let's say c is the index of the current position. So, initially, c = 0.
STEP 2
If it is 7, you found the index. It's c. If you've reached the end of the array, break out.
STEP 3
If it's not, then 7 must be atleast |array[c]-7| positions away because you can only add a unit per index. Therefore, Add |array[c]-7| to your current index, c, and go to STEP 2 again to check.
In the worst case, when there are alternate 1 and -1s, the time complexity may reach O(n), but average cases would be delivered quickly.

Here I am giving the implementation in java...
public static void main(String[] args)
{
int arr[]={4,5,6,5,4,3,2,3,4,5,6,7,8};
int pos=searchArray(arr,7);
if(pos==-1)
System.out.println("not found");
else
System.out.println("position="+pos);
}
public static int searchArray(int[] array,int value)
{
int i=0;
int strtValue=0;
int pos=-1;
while(i<array.length)
{
strtValue=array[i];
if(strtValue<value)
{
i+=value-strtValue;
}
else if (strtValue==value)
{
pos=i;
break;
}
else
{
i=i+(strtValue-value);
}
}
return pos;
}

Here is a divide-and-conquer style solution. At the expense of (much) more bookkeeping, we can skip more elements; rather than scanning left-to-right, test in the middle and skip in both directions.
#include <stdio.h>
#include <math.h>
int could_contain(int k, int left, int right, int width);
int find(int k, int array[], int lower, int upper);
int main(void){
int a[] = {4,3,2,3,2,3,4,5,4,5,6,7,8,7,8};
printf("7 first occurs at index %d\n",find(7,a,0,14));
printf("but 9 first \"occurs\" at index %d\n",find(9,a,0,14));
return 0;
}
int could_contain(int k, int left, int right, int width){
return (width >= 0) &&
(left <= k && k <= right) ||
(right <= k && k <= left) ||
(abs(k - left) + abs(k - right) < width);
}
int find(int k, int array[], int lower, int upper){
//printf("%d\t%d\n", lower, upper);
if( !could_contain(k, array[lower], array[upper], upper - lower )) return -1;
int mid = (upper + lower) / 2;
if(array[mid] == k) return mid;
lower = find(k, array, lower + abs(k - array[lower]), mid - abs(k - array[mid]));
if(lower >= 0 ) return lower;
upper = find(k, array, mid + abs(k - array[mid]), upper - abs(k - array[upper]));
if(upper >= 0 ) return upper;
return -1;
}

const findMeAnElementsFunkyArray = (arr, ele, i) => {
const elementAtCurrentIndex = arr[i];
const differenceBetweenEleAndEleAtIndex = Math.abs(
ele - elementAtCurrentIndex
);
const hop = i + differenceBetweenEleAndEleAtIndex;
if (i >= arr.length) {
return;
}
if (arr[i] === ele) {
return i;
}
const result = findMeAnElementsFunkyArray(arr, ele, hop);
return result;
};
const array = [4,5,6,5,4,3,2,3,4,5,6,7,8];
const answer = findMeAnElementsFunkyArray(array, 7, 0);
console.log(answer);
Wanted to include a recursive solution to the problem. Enjoy

Related

Permutations in lexicographical order with not unique characters

I want to make function to output all possible permutations from input string, in lexicographical order.
I have the following code:
void permutations_print(char *permutations, int index, int length) {
if (index == length) {
printf("\"%s\"\n", permutations);
}
for (int i = index; i < length; i++) {
rotate(permutations, i, index);
permutations_to_array(permutations, index + 1, length);
rotate_back(permutations, index, i);
}
}
void rotate(char to_swap[], int i, int j) {
char temp = to_swap[i];
for (int k = i; k > j; k--) {
to_swap[k] = to_swap[k - 1];
}
to_swap[j] = temp;
}
void rotate_back(char to_swap[], int i, int j) {
char tmp = to_swap[i];
for (int k = i; k < j; k++) {
to_swap[k] = to_swap[k + 1];
}
to_swap[j] = tmp;
}
The input string permutations is permutations_print is sorted.
It works without any issues for permutations with just unique characters, but I need it to work also for character non-unique strings, any ideas how to tweak it / modify it / to work? I have to use recursion and should not use any kind of sorting and I should not store it in any array, just print. And I want to print all, even duplicates.
Warning: not a C programmer, so my code can definitely be improved.
You can do it iteratively with something like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void swap(char* array, int i, int j);
void reverse(char* array, int left, int right);
bool nextPermutation(char* array, int n);
int compareCharacters(const void * a, const void * b);
void printPermutations(char *permutations, int length);
int main() {
char myArray[] = "hey";
printPermutations(myArray, 3);
return 0;
}
void printPermutations(char *array, int length) {
qsort(array, length, sizeof(char), compareCharacters);
*(array + length) = '\0';
do {
printf("%s\n", array);
} while (nextPermutation(array, length));
}
int compareCharacters(const void * a, const void * b) {
return (*(char*)a - *(char*)b);
}
bool nextPermutation(char* array, int n) {
if (n <= 1) {
return false;
}
// Find index, swapIndex1, of rightmost number that has a number greater than it
int swapIndex1;
for (swapIndex1 = n - 2; swapIndex1 >= 0; --swapIndex1) {
if (array[swapIndex1] < array[swapIndex1 + 1]) {
break;
}
}
if (swapIndex1 == -1) {
return false;
}
// Find index, swapIndex2, of smallest number to the right of that and greater than it
int swapIndex2 = swapIndex1 + 1;
int minToRight = array[swapIndex2];
for (int i = swapIndex2 + 1; i < n; ++i) {
if (array[i] <= minToRight && array[i] > array[swapIndex1]) {
minToRight = array[i];
swapIndex2 = i;
}
}
// Swap values at swapIndex1 and swapIndex2
swap(array, swapIndex1, swapIndex2);
// Reverse values from swapIndex1+1 to n-1
reverse(array, swapIndex1 + 1, n - 1);
return true;
}
void swap(char* array, int i, int j) {
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
void reverse(char* array, int left, int right) {
for (; left < right; ++left, --right) {
swap(array, left, right);
}
}
The algorithm is described here. See the comments section for an example/explanation, or see transcription below:
Let's pretend we're finding the next largest permutation of digits from 1-9.
For example, suppose we have: 123479865
We want to find the smallest number greater than 123479865 that can be obtained by rearranging the digits of 123479865.
What this means is that we have to make at least one digit bigger than it currently is. If we had our choice, we would want to make the rightmost digit bigger since that will result in the smallest change. If we were to make a left number bigger, it would result in a bigger change in value.
e.g.: 123479865 => 123479866 is a much smaller change than 123479865 => 223479865.
Therefore, we want to find the farthest digit to the right that we can make bigger. In order to make a digit bigger, we have to find another number bigger than it within our sequence and then swap the two.
Note: we cannot swap a number (e.g., 5) with a number to its left (e.g., 6), because then we would be decreasing the value of a digit to our left, which would make our overall number smaller. For example, if we swapped 5 with 6, we would get 123479856, which is smaller than 123479865. Thus, we always swap with a number to our right.
So let's go through 123479865, starting with the rightmost digit.
There is nothing bigger than 5 to the right of 5, so we can't make 5 bigger.
Now let's consider 6. There is nothing bigger than 6 to the right of 6, so we can't make 6 bigger.
Now let's consider 8. There is nothing bigger than 8 to the right of 8, so we can't make 8 bigger.
Now let's consider 9. There is nothing bigger than 9 to the right of 9, so we can't make 9 bigger.
Now let's consider 7. There are a few numbers to the right of 7 that are bigger than 7, namely: 9 and 8. Therefore, we can make 7 bigger. We want to make it bigger by the least amount, so we should swap it with the smallest value that is bigger than 7. In other words, we should swap 7 with 8. That gives us: 123489765.
The number 123489765 is bigger than 123479865, but we can actually make it smaller while maintaining that it's bigger than 123479865. We can do this because we now have infinite freedom to change any of the following digits: 123489765 (anything to the right of 8). Those numbers can be as small as possible because the 8 to their left ensures that the new number is always bigger.
The best way to make the digits 9765 smaller is to sort them in increasing order, giving us 5679. Sorting works because the leftmost place values contribute the most to the overall value. Therefore, we want the leftmost digits to be the smallest digits.
That leaves us with 123485679, which is our answer.
Note: we don't actually have to sort the numbers to the right of 8. We can actually reverse their order because we know that the numbers from the right side to 8 are in increasing order (because earlier, we stopped the first time we got to a number that was smaller than its previous number).

Algorithm to find a consecutive sub-sequence whose sum would be a asked number M from a sequence of numbers in O(n)

Lets say we have an array of positive numbers and we were given a value M. Our goal is to find if there is a consecutive sub sequence in the array of positive numbers such that the sum of the sequence is exactly equal to sum M. If A[1],A[2],....A[n] is an array then we have to find if there exist i and j such that A[i]+...+A[j] = M.
I am trying to get the O(n) solution using greedy approach.
I believe you can solve this in linear time with a pointer chasing algorithm.
Here's the intuition. Start off a pointer at the left side of the array. Keep moving it to the right, tracking the sum of the elements you've seen so far, until you either hit exactly M (done!), your total exceeds M (stop for now, adding in more elements only makes it worse), or you hit the end of the array without reaching at least M (all the elements combined are too small). If you do end up in a case where the sum exceeds M, you can be guaranteed that no subarray starting at the beginning of the array adds up to exactly M, since you tried all of them and they were either too small or too big.
Now, start a second pointer at the first element and keep advancing it forward, subtracting out the current element, until you either get to exactly M (done!), you reach the first pointer (stop for now), or the total drops below M (stop for now). All the elements you skipped over with this pointer can't be the starting point of the subarray you're looking for. At this point, start marching the first pointer forward again.
Overall, each pointer advances at most n times and you do O(1) work per step, so this runs in time O(n). Plus, it uses only O(1) space, which is as good as it's going to get!
This is a standard two pointer problem. First of all, create an array, prefix that will store the prefix sum of the given array, say arr.
So
prefix[i] = arr[1] + .. + arr[i]
Start with two pointers, lower and upper. Initialize them as
lower = 0
upper = 1
(Note: Initialize prefix[0] to 0)
Now, try to understand this code:
lower = 0, upper = 1;
while(upper <= n) { // n is the number of elements
if(prefix[upper] - prefix[lower] == m) {
return true;
} else if(prefix[upper] - prefix[lower] > m) {
lower++;
} else {
upper++;
}
}
return false;
Here we are using the fact that the array consists of positive integers,
hence prefix is increasing
Assume that the subarray with indices X ≤ i < Y might be the solution.
You start with X = 1, Y= 1, sum of elements = 0.
As long as the sum is less than M, and Y <= n, increase the sum by array [Y] and replace Y with Y + 1.
If the sum is equal to M, you found a solution.
If the sum is less than M, you remove array elements at the start: As long as the sum is greater than M, subtract array [X] from the sum and replace X with X + 1. If the sum became equal to M, you have a solution. Otherwise you start with the first loop.
(edited: see templatetypedef's comment)
Use the two indices approach: increase the lower index if subsequence too small otherwise increase higher index.
Example:
void solve(int *a, int n, int M) {
if (n <= 0) return;
int i, j, s;
i = 0, j = 0, s = a[j];
while (j < n) {
if (s == M) {
printf("%dth through %dth elements\n", i + 1, j + 1);
return;
} else if (s < M) {
j++;
s += a[j];
} else {
s -= a[i];
i++;
}
}
}
public class FindSumEquals {
public static void main(String[] args) {
int n = 15;
System.out.println("Count is "+ findPossible(n));
}
private static int findPossible(int n) {
int temp = n;
int arrayLength = n / 2 + 2;
System.out.println("arrayLength : " + arrayLength) ;
int a [] = new int[arrayLength];
int count = 0;
for(int i = 1; i < arrayLength; i++){
a[i] = i + a[i - 1];
}
int lower = 0, upper = 1;
while(upper <= arrayLength - 1) {
if(a[upper] - a[lower] == temp) {
System.out.println("hello - > " + ++lower + " to "+ upper);
upper++;
count++;
} else if(a[upper] - a[lower] > temp) {
lower++;
} else {
upper++;
}
}
return count;
}
}

Minimum number of swaps to convert a string into another string [duplicate]

This question already has answers here:
Finding the minimum number of swaps to convert one string to another, where the strings may have repeated characters
(3 answers)
Closed 8 years ago.
Problem statement:
Find the minimum number of swaps to convert one string into another of the same length, which may or may not have duplicate characters; arbitrary swaps are allowed.
min_swaps('kamal', 'amalk') -> 3
# 1 2 3
# kamal -> lamak -> aamlk -> amalk
Note: There are many of these questions on SO, but none that seem to apply to arbitrary swaps.
Initial Approach:
let s1 = 'kamal'
let s2 = 'amalk'
Assume that s1 is the "correct" ordering, that is its elements map to sequence from 0 -> N-1 in increasing order.
0 1 2 3 4
k a m a l
Now create an array P that is a mapping from letters in s2 to the correct index in s1:
1 2 3 4 0
a m a l k
P = [1,2,3,4,0]
Now we can count the number of array inversions in P using a modified mergesort, which will give us the number of elements that are out of order.
Modified mergesort:
int main(int argc, char ** argv) {
int array[] = { 1,2,3,4,0 };
int array_size = sizeof(array)/sizeof(array[0]);
int inversions = merge_sort(array, 0, array_size - 1);
printf("Found %d inversions\n", inversions);
return 0;
}
int merge_sort(int a[], int start, int end) {
if ( end > start ) {
int mid = start + (end - start) / 2;
int x = merge_sort(a, start, mid);
int y = merge_sort(a, mid + 1, end);
int z = merge(a, start, mid, end);
return x + y + z;
}
return 0;
}
int merge(int a[], int start, int mid, int end) {
int l = start, r = mid + 1;
int i = 0;
int temp[end - start + 1];
int splitInversionCount = 0;
while ( l <= mid && r <= end ) {
if ( a[l] < a[r] ) {
temp[i++] = a[l++];
}
else {
splitInversionCount += mid - l + 1;
temp[i++] = a[r++];
}
}
// copy whichever half of the array remains
while ( l <= mid ) {
temp[i++] = a[l++];
}
while ( r <= end ) {
temp[i++] = a[r++];
}
// copy temp back into a
int k;
for(k = 0; k < i; k++) {
a[k + start] = temp[k];
}
return splitInversionCount;
}
The problem with this is that it gives the minimum number of swaps with only adjacent elements, this returns 4 instead of 3.
Question:
Is there any way to extend this algorithm to capture arbitrary swaps as well? Or do I need a completely different approach?
I have not a full solution yet, but I think it's useful to state this to help others.
Let's assume the strings have size N. Let's call k the number of characters that are already in their position. Initially k <= N
A swap can have either:
Set 2 characters in the right position. Increase k by 2
Set 1 character in the right position. Increase k by 1
Do nothing useful, k remains the same.
You can always make a move of the second kind, and you can find it in O(n) time. Just take one character out of pos, and find the position where it needs to be, then swap.
You shouldn't make a swap of the first type as soon as you see one, as you could break too other moves that set 2 characters at the same time. If you do so you'll end up setting 4 chars in 3 moves when you could have done it in 2.
Making a move of the third kind may allow making 2 moves of the first kind, so all three kind of moves are useful.

Algorithm to find maximum sum of elements in an array such that not more than k elements are adjacent

I came across this question. Given an array containing only positive values, you want to maximize the sum of chosen elements under the constraint that no group of more than k chosen elements are adjacent. For example if input is 1 2 3 1 7 9 (n=6 and k =2). The output will be 21, which comes from picking the elements _ 2 3 _ 7 9. My simple DP solution is this
#include<stdio.h>
#include<limits.h>
#include<malloc.h>
long maxsum(int n,int k,long *sums){
long *maxsums;
maxsums = malloc(sizeof(long)*n);
int i;
long add = 0;
for(i=n-1;i>=n-k;i--){
add += sums[i];
maxsums[i] = add;
}
for(i = n-k-1;i>=0;i--){
int j;
long sum =0,max = 0,cur;
for(j=0;j<=k;j++){
cur = sum;
if((i+j+1)<n)
cur += maxsums[i+j+1];
if(cur > max) max = cur;
sum += sums[i+j];
}
maxsums[i] = max;
}
return maxsums[0];
}
int main(){
int cases=0,casedone=0;
int n,k;
long *array;
long maxsum = 0;
fscanf(stdin,"%d %d",&n,&k);
array = malloc(sizeof(long)*n);
int i =0;
while(casedone < n){
fscanf(stdin,"%ld",&array[casedone]);
casedone++;
}
printf("%ld",maxsum(n,k,array));
}
But I am not sure whether this is the efficient solution. Can the complexity be further reduced? Thanks for your help
Your code is correct (at least the thought is correct), also, Up to now, I have not found any wrong test data. Follow your thought, we can list the DP equation
P(v)=max{sum(C[v]~C[v+i-1])+P(v+i+1),0<=i<=k}
In this equation, P(v) means the maximum in {C[v]~C[n]}(we let {C[1]~C[n]} be the whole list), so we just need to determine P(1).
I have not find a better solution up to now, but your code can be optimized, after you determine P(v), you can save the data i, so when you find P(v-1), you can just compare sum(C[v-1]+C[v]~C[v+i-1])+P[v+i+1] with P[v+1]+C[v] when i!=k, the worst complexity is the same, but the best complexity is linear.
I think this will work :
findMaxSum(int a[], int in, int last, int k) { // in is current index, last is index of last chosen element
if ( in == size of a[] ) return 0;
dontChoseCurrent = findMaxSum(a, in+1, last, k); // If current element is negative, this will give better result
if (last == in-1 and k > 0) { // last and in are adjacent, to chose this k must be greater than 0
choseCurrentAdjacent = findMaxSum(a, in+1, in, k-1) + a[in];
}
if (last != in-1) { // last and in are not adjacent, you can chose this.
choseCurrentNotAdjacent = findMaxSum(a, in+1, in, k) + a[in];
}
return max of dontChoseCurrent, choseCurrentAdjacent, choseCurrentNotAdjacent
}

In less-than-linear time, find the duplicate in a sorted array

Today, an interviewer asked me this question. My immediate response was that we could simply do a linear search, comparing the current element with the previous element in the array. He then asked me how the problem could be solved in less-than-linear time.
Assumptions
The array is sorted
There is only one duplicate
The array is only populated with numbers [0, n], where n is the length of the array.
Example array: [0,1,2,3,4,5,6,7,8,8,9]
I attempted to come up with a divide-and-conquer algorithm to solve this, but I'm not confident that it was the right answer. Does anyone have any ideas?
Can be done in O(log N) with a modified binary search:
Start in the middle of the array: If array[idx] < idx the duplicate is to the left, otherwise to the right. Rinse and repeat.
If no number is missing from the array, as in the example, it's doable in O(log n) with a binary search. If a[i] < i, the duplicate is before i, otherwise it's after i.
If there is one number absent and one duplicate, we still know that if a[i] < i the duplicate must be before i and if a[i] > i, the absent number must be before i and the duplicate after. However, if a[i] == i, we don't know if missing number and duplicate are both before i or both after i. I don't see a way for a sublinear algorithm in that case.
I attempted to come up with a divide-and-conquer algorithm to solve this, but I'm not confident that it was the right answer.
Sure, you could do a binary search.
If arr[i/2] >= i/2 then the duplicate is located in the upper half of the array, otherwise it is located in the lower half.
while (lower != upper)
mid = (lower + upper) / 2
if (arr[mid] >= mid)
lower = mid
else
upper = mid-1
Since the array between lower and upper is halved in each iteration, the algorithm runs in O(log n).
ideone.com demo in Java
Difference between sum of given array elements and sum of 0 to n-1 natural numbers gives you the duplicated element.
Sum of 0 to n-1 elements is (N * N-1)/2
example array is [0,1,2,3,4,5,6,7,8,8,9]
sum of 0 to 9 natural numbers is : 45
sum of given array elements : 53
53-45 = 8 Which is the duplicated element
#include <bits/stdc++.h>
using namespace std;
int find_only_repeating_element(int arr[] , int n){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + (high - low)/2;
if(arr[mid] == arr[mid + 1] || arr[mid] == arr[mid - 1]){
return arr[mid];
}
if(arr[mid] < mid + 1){
high = mid - 2;
}else{
low = mid + 1;
}
}
return -1;
}
int main(int argc, char const *argv[])
{
int n , *arr;
cin >> n;
arr = new int[n];
for(int i = 0 ; i < n ; i++){
cin >> arr[i];
}
cout << find_only_repeating_element(arr , n) << endl;
return 0;
}
How about that? (recursion style)
public static int DuplicateBinaryFind(int[] arr, int left, int right)
{
int dup =0;
if(left==right)
{
dup = left;
}
else
{
int middle = (left+right)\2;
if(arr[middle]<middle)
{
dup = DuplicateBinaryFind(arr,left, middle-1);
}
else
{
dup = DuplicateBinaryFind(arr, middle+1, right);
}
}
return dup;
}
The example array is a little bit different from your question. Since n is the length of array and there are one and only duplicate in array, the value of each element in array should be in [0,n-1].
If that is true, then this question is the same one with How to find a duplicate element in an array of shuffled consecutive integers?
The following code should find the duplicate in O(n) time and O(1) space.
public static int findOnlyDuplicateFromArray(int[] a, boolean startWithZero){
int xor = 0;
int offset = 1;
for(int i=0; i < a.length; i++){
if(startWithZero)
xor = xor ^ (a[i] + offset) ^ i;
else
xor = xor ^ a[i] ^ i;
}
if(startWithZero)
xor = xor - offset;
return xor;
}

Resources