Interview Question


Country: United States




Comment hidden because of low score. Click to expand.
6
of 6 vote

Assume all this is in a function that returns true if a duplicate is found:

0) Needed is an abs. value function or macro:

#define ABS(x)  ( (x)<0?-(x):(x) )

1) Have a boolean flag to check if you have duplicate 0's.

bool seenzero;
for(i=0; i<N; i++)
	if( a[i] == 0 )
		if( seenzero ) return true;  //zero was seen before
	else	
		seenzero=true;

So the zero check is ~1n single pass, plus 1 boolean var. space.

Now we can assume the array has values in the range 1 to n-1 only.
This means a few things:
1) We can flip any value in the array from positive to negative and not "lose" information, because abs(a[i]) == original(a[i]) regardless if we flipped the sign.
So we can flip signs as we desire.
2) Since 0 can no longer be a value, we "know" if a[i] < 0, that "we" are the ones that had flipped it's sign. ( 0 would mess this up because -0 == 0 ).
3) Since the values are in the range 1 to n-1 and len(a)==n, all the original values of the array can index the array itself.

Now comes the code that someone has to do on paper to get it the first time:

for(int i=0; i<N; i++)
{
	// this means abs(a[i]) was used as an index into a[ ] already
	if( a[ abs(a[i]) ]  < 0 ) return true;  

	// first time abs(a[i]) used to index a[ ], change sign below to trap second time
	a[ abs(a[i]) ] *= -1;
}

return false; //neither the zerocheck or the self-indexing-sign-flipping caught the error

Type this raw, so hope it's okay.

Runtime O(n) , two passes with constant effort on each element during each pass
Aux. storage O(1) ... just the index i, and boolean seenzero (1 stack frame, registers)

Add 1 more pass if you need the array back to it's original form (take abs of each element).

- S O U N D W A V E October 16, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

the post had the formatting messed up in a few places (some extra ;'s appear, like in abs macro):
Redo:

#define ABS(x)  ( (x) < 0 ? -(x) : (x) )

- S O U N D W A V E October 16, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Small adjustment:

On the first pass (zero check), keep the position of the zero:

int zeropos = -1;

for(i=0; i<N; i++)
{
	if(a[i] == 0) 
		if(zeropos != -1) return true; //duplicate 0
	else
		zeropos = i  //position of 0
}

Then add an extra check (either as part of the sign flipping for loop, or as an extra pass before hand, to see if there are duplicate "zeropos" values in the array:

Here I show the extra pass pre-signflipcode:

bool extracheck
for(i=0; i<N; i++)
{
	if( a[i] == zeropos ) 
		if( extracheck ) return true; //duplicate "zeropos" values in a[ ]
	else
		extracheck = true;
}

Again, I need to compile and test.

- S O U N D W A V E October 16, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Sorry, but above I was talking "out loud" and building the solution by iteration (and explaining).

It's better if I drop a clean almalgamation of it.

This also should be "nondestructive" on the array.

collabedit.com/bbptb

Again, no compiling/testing done.

#define ABS(x)  ((x)<0 ? -(x) : (x))

/* put this in a function that return true if duplicate is found in array a[] of size N */

int zeropos = -1;  //position of any 0 found in array

for(i=0; i<N; i++)
    if(a[i] == 0) 
        if(zeropos != -1) return true; //duplicate 0 found (and array is untouched, so return immediately )
    else
        zeropos = i  //position of 0

a[zeropos] = 1;  //set to 1 so the next for loop works for dup="zeropos"

bool dupfound;    // true means we found duplicate 
for(int i=0; i<N; i++)
{
    // this means abs(a[i]) was used as an index into a[ ] already
    if( a[ abs(a[i]) ]  < 0 ) { dupfound = true; break; }  

    // first time abs(a[i]) used to index a[ ], change sign below to trap second time
    a[ abs(a[i]) ] *= -1;
}

/* next part "recreates" the original array */
for(int i=0; i<N; i++)
    if( a[i] < 0 ) a[i] *=-1;
    
a[zeropos]=0; //recreate the zero element

return dupfound;

- S O U N D W A V E October 17, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

There is a small bug there (which when coding people will catch); I'll leave it in there as an exercise.

- S O U N D W A V E October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

//test the code
	public static void main(String[] args) {
		int [] 	array1 = {0,1,2,3,4,5};
		int [] 	array2 = {0,5,2,3,4,5};
		
		System.out.println("#1: "+duplicateChecker(array1));
		System.out.println("#2: "+duplicateChecker(array2));
	}


	/**You have an array of length n, containing values of length 0 to n-1.  Tell me if there exists a duplicate (return true or false).  Do it in constant space and O(n) time.*/
	public static boolean duplicateChecker(int[] array)  {
		int val;
		int len = array.length;
		
		boolean[] exists = new boolean[len];
		for (int i = 0; i < len; i++) {
			val = array[i];
			if (exists[val]) return true;
			exists[val] = true;
		}
		
		return false;
	}

- Just Bored :) October 16, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

you code uses O(n) extra memory.

- Miguel Oliveira October 16, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Miguel True & thank you for the review.

I suppose it depends on the memory/processor constraints and expected input. Mine involves the least number of steps, but uses more memory. Yours has about 2x the steps, and destroys the original array in the process. The top-voted comment is quite clever, using a 'negative' flag, but in the process performs about 3x the operations without destroying the original array.

I only recently began these types of interviews, and noticed they're much more picky about memory usage than they are the number of steps in the process.

- JonG October 17, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

the question says using constant space, so the interviewer wants us to avoid the trivial solutions.

- Miguel Oliveira October 17, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This also should be "nondestructive" on the array.
* O(n) time
* O(1) space
* array left untouched after result returned

collabedit.com/bbptb

Again, no compiling/testing done.

#define ABS(x)  ((x)< 0 ? -(x) : (x))

/* put this in a function that return true if duplicate is found in array a[] of size N */

int zeropos = -1;  //position of any 0 found in array

for(i=0; i<N; i++)
    if(a[i] == 0) 
        if(zeropos != -1) return true; //duplicate 0 found (and array is untouched, so return immediately )
    else
        zeropos = i  //position of 0

a[zeropos] = 1;  //set to 1 so the next for loop works for dup="zeropos"

bool dupfound;    // true means we found duplicate 
for(int i=0; i<N; i++)
{
    // this means abs(a[i]) was used as an index into a[ ] already
    if( a[ abs(a[i]) ]  < 0 ) { dupfound = true; break; }  

    // first time abs(a[i]) used to index a[ ], change sign below to trap second time
    a[ abs(a[i]) ] *= -1;
}

/* next part "recreates" the original array */
for(int i=0; i<N; i++)
    if( a[i] < 0 ) a[i] *=-1;
    
a[zeropos]=0; //recreate the zero element

return dupfound;

- S O U N D W A V E October 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

The sum of first n numbers starting from 0,1,2, _ _ _ , n-1 is n(n-1)/2.
We can calculate the sum and then a for loop to calculate the sum of elements of array. If the two sums are not equal then return true else false. 

OverallComplexity O(n)

- SumitGaur April 15, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Basically, if there are no duplicates, we receive a permutation of the numbers 0..n-1.
We can rearrange the array such that number i is at position i.
Take this example: 0,3,2,5,4,1
0 is in the correct position.
3 is at position 1, we will swap it with the number at position 3 (5) to put it in the right position
0,5,2,3,4,1
now 5 is wrong, swap it with the number at position 5 (1)
0,1,2,3,4,5
now 1 is ok. 2, 3, 4 and 5 are too.

If at any step we try to swap a number into a position which already contains that number, then there are duplicates.

#include <iostream>
using namespace std;

bool Check(int* v, int n) {
	for (int i = 0; i < n; i++)
		if (v[i] != i) {
			do {
				if (v[v[i]] == v[i])
					return true;
				swap(v[i], v[v[i]]);	
			} while (v[i] != i);
		}
	return false;	
}
int main() {
	int v1[] = {0,1,2,3,4,5};
	int v2[] = {0,5,2,3,4,5};
	int v3[] = {0,3,2,5,4,1};
	cout << Check(v1, 6) << endl;
	cout << Check(v2, 6) << endl;
	cout << Check(v3, 6) << endl;
	return 0;
}

- Miguel Oliveira October 16, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

bool dup_exists(vector<int>& v)
{
	// this's order O(N) .. the both 
	// loop combined only iterate all element only once.
	for (int i = 0; i < v.size(); i++)
	{
		while (v[i] != i) 
		{
			int temp = v[v[i]];
			if (temp == v[i]) return true;
			v[v[i]] = v[i];
			v[i] = temp;
		}
	}
	return false;

}

- Anonymous October 16, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public boolean solution(int[] list) {
	int[] solutions = new int[list.length];
	for(int i : list) {
		solutions[i] = 1;
	}
	for(int k : solutions) {
		if(k == 0) {
			return false;
		}
	}
	return true
}

- michael October 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

for(i=0;i<n;i++)
{
sum=sum+arr[i];
sum=sum-(i+1);
}
if(sum==0)
printf("No duplicate element in array\n");
else
printf("duplicate element occure in array\n");

- Anonymous October 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

for(i=0;i<n;i++)
{
sum=sum+arr[i];
sum=sum-(i+1);
}
if(sum==0)
printf("No duplicate element in array\n");
else
printf("duplicate element occure in array\n");

- anonymous October 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

How about using XOR:

a[n+1] = {0};
for(int i =0; i < n; ++i
{
	int k = array[i] + 1;	// add one is for the element zero
	if (a[k]^k == 0)	
		return true;
	else
		a[k] = k;
}

return false;

- Jay October 18, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

why are you using xor instead of a[k] == k?

- Miguel Oliveira October 18, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You are right.
so we just need to add a for loop before mine

for(j = 0; j < n; ++j)
{
a[j] = j;
}

- Jay October 18, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I just think of a way.
in C++, there is a "set" container.
it will only store unique value.

So go along the array and insert value into the container, with complexity O(n).
compare the size of this container and original array.
if they are the same, there are no duplicate.

- Jay October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

2 problems:
1) Set operations run in O(log n), so the overall solution will work in O(n log n), not O(n).
2) You would be using extra O(n) memory, violating the constant space constraint.

Since the values are only in the interval [0, n[ we could just use a boolean array with n positions to keep it O(n), but it still violates 2).

- Miguel Oliveira October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

It is not warranted that the array is sorted or if every element is placed in its correct index within the specified range. We can still have an O(n) algorithm using XOR of the elements of the array. If the final XOR-ed value is zero that means all elements are of even number, so they cancel each other out. Otherwise, the result of this XOR is the element with no duplicate.

bool CheckDuplicate(int *a, int n)
{
if(a==NULL || n<=0)
 return false;
result=0;
for(i=0;i<n;i++)
  result^=a[i];
return (result==0 ? true : false);

- Anonymous October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

return sum(a[i]) != n*(n+1)/2

- Anonymous October 16, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your code is not guaranteed to work.

An array of length 4 with no duplicate should return a sum of 6 (0+1+2+3).

Your code is easily defeated with the input {0,0,3,3}.

- Clever, but failure prone. October 16, 2013 | Flag
Comment hidden because of low score. Click to expand.


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More