Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: Phone Interview




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

backtracing.
1. sort x first.
2. iterate through x, find a unused digit that is greater than or equal to the target digit in y.
2.a if we can find a digit that is strictly greater than that in y, we find a solution, add all unused digits in x into the result in ascending order
2.b if we can only find a digit in x that is equal to the target digit in y, we continue this execution path.

def rearrange(x, y):
	assert len(x) == len(y)
	x.sort()
	used_x = [False] * len(x)
	result = []
	rearrange_helper(x, y, used_x, result)
	return result

def rearrange_helper(x, y, used_x, result):
	#print(result)
	if all(used_x):
		return False
	target_yi = len(result)
	for i in range(len(x)):
		if not used_x[i]:
			if x[i] > y[target_yi]:
				used_x[i] = True
				result.append(x[i])
				result += [x[i] for i in range(len(x)) if not used_x[i]]
				return True
			elif x[i] == y[target_yi]
				used_x[i] = True
				result.append(x[i])
				if rearrange_helper(x, y, used_x, result):
					return True
				else:
					used_x[i] = False
					del result[-1]
	return False

- gnahzy October 31, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
3
of 3 votes

Because all digits are in [0, 9], so instead of sorting, counting each of them might be faster, down from O(n*log(n)) to O(n). The remaining is the same. Finding a target digit needs O(1) time, so the total is still O(n).

- Anonymous October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

What happens in this case where set1={2,4,1,0} and set2={2,4,1,9}

Here you will need to notify backwards to choose from a number which is greater at a previous level.

- Anonymous October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

yea, that's why I sort set1 first. in this way, the next we select is greater than the previous one.

- gnahzy October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes
{{{how about adding following conditions to your logic. If x<y: 1. sort x and when you find a value in sorted x which is equal to target value in y, start with next value in sorted x and append remaining values just as you mentioned. 2. If matching value in sorted x is found, but itself is the last value (or) no match value for target value in y is found in sorted x then print "no such arrangement is possible" - ajit October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is O(x^2) in the worst-case.

Consider if Y is already as big as it can be, or sorted in descending order. Now you will traverse to the end of x at each iteration, resulting in a quadratic algorithm.

- Steve October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@steve. yes, you are right. one opt that i can think of is to use binary search to find a right digit in x that is greater than or equal to the corresponding digit in y, which reduce the time to O(nlogn).

- gnahzy October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think linear time can be achieved. Assume the length of x and y are equal.
The naive idea is counting the number but not sorting, so that constant time needed to find a suitable candidate.

def arrange( ypos )
   ydigit = y[ypos]
   if ypos == last position of y
       if there is nonzero element in count whose index is larger than ydigit # constant time
          
          result[ypos] = the index of the nonzero element
          return true
       else return false
   if count[ydigit] > 0
       count[ydigit]--
       if arrange(ypos + 1)
          result[ypos] = ydigit
          return true
       else
          if there is i such that i > ypos and count[i] > 0 # constant time
             result[ypos] = the smallest i
             result[ypos + 1, ..., ylast] = the smallest number can be formed by the rest in count # linear time
             return true
          else
             return false
   else
       if there is i such that i > ypos and count[i] > 0 # constant time
          result[ypos] = the smallest i
          result[ypos + 1, ..., ylast] = the smallest number can be formed by the rest in count # linear time
          return true
       else
          return false

def main()
    for i in x
       count[i]++

    if arrange(left-most index)
         print result
    else
         no arrange satisfying the requirement.

Since scanning the count array require constant time, the alg. would be linear time.
Don't know whether it will work :)

- warrior November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This solution is partially incorrect. It will work optimally with following modifications:
1. Sort the X so that we can do binary search every time.
2. When you look for an element in X and there is no element in X that is equal to the digit we are looking for, then you also need to consider the case when unused digit is smaller than the digit we are looking for
3. While doing binary search, if you find the desired digit multiple times, process it just once.

Optimum time complexity would be O(n*logn)

- Epic_coder November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You don't need to backtrack if you are out of digits that are higher then the one in y.
Why not just generate the largest possible number with the remaining digits (even though it will be lower then y) and then run next permutation algorithm on the result?

- cristian.botau November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Why consider smaller one?
Consider the situation that we are in position i and all j < i s.t. result[j]==y[j], and there remains no digit equivalent to y[i]. If we choose a smaller one, since it's the most significant digit different with y, no matter how we permute remaining digit, the result wouldn't larger than y. On the other hand, if we choose a digit larger than y[i], we are guaranteed that the result > y. So we just need to find the smallest permutation for the digit left and ignore what remains in y. That's why I think only larger digit should be considered. May I know why this is wrong? Thx

- warrior November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Later edit: @warrior: in case your last reply was not referring to my comment then just ignore what I just wrote :)

I didn't say that your solution is incorrect (it is actually correct), but i don't like the fact that it uses backtracking.

Regarding to what I proposed you misunderstood one thing: it doesn't permute the remaining digits, it finds the next permutation for the whole number.

Here is an example:
X = [1, 6, 7, 3, 2], Y = [6, 7, 8, 9, 1]

Algorithm:
[6 ?] --> [6, 7, ? ] -- no remaining larger digits? ---> [6, 7, 3, 2, 1] -- next permutation --> [7, 1, 2, 3, 6]

- cristian.botau November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@cristian.botau
Got ur idea. So an algorithm to calc next smallest permutation is needed. Is there any simple algorithm?

- Anonymous November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
2
of 6 vote

You can sort A first, using count sort O(N)

public static int[] getLowest(int[] A, int[] B){
		if(A== null || B == null || A.length != B.length){
			return null;
		}
		int length = A.length;
		if(length < 2){
			if (A[0] < B[0])
				return null; // no solution
			else return A;
		}
		// Assume A is sorted.
		int i = 0; int j = 1; int k = 0;
		while(i<length && j< length && k< length){
			if(A[i] < B[k]){
				swap(A, i, j);
				j++;
			}
			else if(A[i] == B[k]){
				i++; k++;
			}
			else{
				break;
			}				
		}
		return A;
	}

- chinmay.nagarkar November 05, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Looks fine!

- Psycho November 06, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This looks really close but consider the input
A=[1,3,3,4] and B=[4,3,2,1]

I think if you set j=i+1 (after the i++ statement) your algorithm should be good.

- Anon November 06, 2012 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

No that wont work because the value of 'j' crossing the 'length'.
But good example to check the algorithm!

- Psycho November 07, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Good one!

- code_monkey November 08, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

this one cannot solve some of the null cases:

e.g. A=[1,2,3,4], B=[5,6,7,8]

- Judy November 13, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This doesn't work. Consider the case of A = 1234 and B = 2439

This returns 2413, when the correct answer is 3124

- Anonymous November 13, 2012 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

//before calling this function check if the greatest possible number from x is greater then y or not , if it is gthen a hovernum exist.
// has the numbers of x in sorted form
//compv is a function which compares digits of vectors one by one till digitlevel and if it finds any digit of v1 > v2 it returns 1 , if v1<v2 returns -1 , if all equal then returns 0

bool nextNum(set<int> &sx , vector<int> &y , vector<int> &result){
	static int digitlevel = 0;
	set<int>::iterator it;
	if(digitlevel+1 == y.size()){
		result.push_back(*it);
		if(compv(result , y , digitlevel) <=0){ //returns 0 if vectors are equal from 0 to digitlevel
			result.pop_back();
			return -1;
		}else{
			return 0;
		}
	}
	if(compv(result , y , digitlevel) == 0){
		it = sx.lowerbound(y[digitlevel]);
	}
	for(;it!=sx.end();){
		result.push_back(*it);
		sx.erase(it++);
		digitlevel++;
		if(!nextNum(sx,y,result)) return true;
		digitlevel--;
		sx.insert(result.back());
		result.pop_back();
	}
	return -1;
}

- Geek January 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1) Sort the Xs
2) For each y value find the x that is equal to or greater than the y using binary search and this integer in x is part of your rearrangement x.

Time: O(log x * (x+y))

- Steve October 30, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This greedy method is in fact incorrect:

Y: 2146
X: 2145
XSolution: 2154

- Adam October 30, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

wrong. try Y: 2146, X: 2146

- gnahzy October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

True, when the greedy approach fails, an easy modification is just swapping the least 2 significant digits until X is in fact > Y. This can be done in O(x) time.

Thus, the algorithm still works and is O(log x * (x+y))

- Steve October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

Note: I assume x and y have the same number of digits

This is an O(N) algorithm:
Here is pseudocode with explanations:
1. create digits histogram for x in order to be able to efficiently extract a given digit from it

for (int i = 0; i < x.size(); ++i)
    ++histogram[x[i]];

2. start from most significant digit (assuming its index is 0) and basically use the same digit from y on the same position in result. If at some point you don't have that digit, you select the smallest digit higher than the digit you're looking for and then put the remaining digits in increasing order and you have your answer. If there is no larger digit then put the remaining digits in decreasing order.
In this case you've got yourself the closest number to Y, but lower. So you need to generate the next lexicographic permutation - see step 3 (in C++ there is std::next_permutation that just does that).

for (i = 0; i < y.size(); ++i)
{
  try to extract digit y[i] from histogram
  if (y[i] found in histogram) then { result[i] = y[i] }
  else if (there is a digit d in histogram s.t. d > y[i])
       {
          result[i] = the smallest digit d from histogram st d>y[i]
          // put remaining digits in increasing order
          result[(i+1)..y.size()] = histogram.sortIncreasing(); 
          // found the number, woohoo!!
          break for loop; 
        }
        else /* there are only digits lower than y[i] */
        { 
            // put remaining digits in decreasing order
            result[i..y.size()] = histogram.sortDecreasing();  
            // found closest number smaller then y
            break for loop; 
        }   
}

3. Now the variable result is either:
- the result we're looking for, i.e.: the closest number greater or equal to y
- the closest number less than y, case in which we need to generate the next lexicographic permutation of digits

So we need to do this check:

if (result < y)
    result = nextPermutation(result);

- cristian.botau October 31, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Forgot to mention that there is no solution in case nextArrangment() method fails (i.e. this is the highest arrangement for x digits and yet still lower than y).

- cristian.botau October 31, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You method even applies without using next_permutation, with a little bit DP of course. Good thinking!

- huizi.1875 November 15, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Assume x=0003 and y=2999,
answer should be 3000. How does the previous algos work?

- Anonymous November 01, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

or assume x=0123 and y=2999. Above algos fail over here.

- Anonymous November 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

First, you got 2,310, then next_permutation gives you 3,012

- huizi.1875 November 15, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

private static void nextHighest(){
        Set<Integer> y = new HashSet<Integer>();
        y.add(new Integer(1));
        y.add(new Integer(2));
        y.add(new Integer(3));
        y.add(new Integer(4));

        Set<Integer> x = new HashSet<Integer>();
        x.add(new Integer(1));
        x.add(new Integer(2));
        x.add(new Integer(3));
        x.add(new Integer(4));

        String num = "";
        for(int i: y){
            Integer remove =  getDigit(x, i);
            num += remove.toString();
            x.remove(remove);
        }
        System.out.println(num);

    }
    private static Integer getDigit(Set<Integer> x, int close){
        Integer currentLowest = -1;
        for(int i: x){
            if(currentLowest < 1){
                currentLowest = i;
                continue;
            }
            if(currentLowest<=close || i>close && (i+close)<(currentLowest+close)){
                currentLowest = i;
            }
        }
        return currentLowest;
    }

- scott November 09, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

use a hash table to store digits and their occurrences instead of performing the binary search on the sorted array

first to choose the same digit for every position and recursively choose the next position with remaining digits
if it failed to yield a valid combination or the same digit doesn't exist, choose the next larger digit and arrange the position on left with remaining digits in the ascending order
if no lager digit, return false

Time: O(n)

ideone.com/8pDJIG

Test Cases

2 1 4 5
2 1 4 6
[2, 1, 5, 4]


1 6 7 3 2
6 7 8 9 1
[7, 1, 2, 3, 6]


1 2 3 4
2 4 3 9
[3, 1, 2, 4]


1 2 3 4
2 4 1 0
[2, 4, 1, 3]
4
1 3 3 4
4 3 2 1
[4, 3, 3, 1]

public void findClosestPermuntation(int[] x, int[] y)
	{
		int[] z = new int[x.length];
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for(int i = 0; i < 10; i++) map.put(i, 0);
		for(int i: x) map.put(i, map.get(i) + 1);
		r(y, z, 0, map);
		System.out.println(Arrays.toString(z));
	}

	private boolean r(int[] y, int[] z, int i, Map<Integer, Integer> map)
	{
		if(i == z.length) return true;
		int j;
		for(j = y[i]; j < 10 && map.get(j) == 0; j++);
		if(j == y[i]) {
			z[i] = y[i];
			map.put(j, map.get(j) - 1);
			if(r(y, z, i + 1, map)) return true;
			map.put(j, map.get(j) + 1);
			z[i] = 0;
			for(j = y[i] + 1; j < 10 && map.get(j) == 0; j++);
		}
		if(j > 9) return false;
		z[i] = j;
		map.put(j, map.get(j) - 1);
		int k = i + 1;
		for(int p = 0; p < 10; p++) {
			for(int q = 0; q < map.get(p); q++) {
				z[k] = p;
				k++;
			}
		}	
		return true;
	}

- dgbfs November 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Am I the only one that think this is a DFS algo? Any reason why that's not used?

int rearrange (const int & x, const int & y)
{
	std::string xStr;
	{
		std::stringstream ss;
		ss << x;
		xStr = ss.str ();
	}
	std::string yStr;
	{
		std::stringstream ss;
		ss << y;
		yStr = ss.str ();
	}

	std::sort (xStr.begin (), xStr.end ());
	std::reverse (xStr.begin (), xStr.end ());

	std::stack<std::string> newX;
	for (int i = 0; i < xStr.size (); ++i)
	{
		newX.push (xStr.substr (i, 1));
	}

	while (! newX.empty ())
	{
		std::string current = newX.top ();
		newX.pop ();
		std::cout << "\nConsidering [" << current << "]." << std::endl;

		if (current < yStr.substr (0, current.size ()))
		{
			continue;
		}
		if (current.size () == yStr.size () && current > yStr)
		{
			std::stringstream ss;
			ss << current;
			int retVal (0);
			ss >> retVal;
			return retVal;
		}

		std::string mark;	// Handle duplicates
		{
			for (int i = 0; i < xStr.size (); ++i)
			{
				mark.append ("F");
			}
			for (int i = 0; i < current.size (); ++i)
			{
				std::size_t tmp = xStr.find (current.at (i));
				if (std::string::npos == tmp)
				{
					// This should never happen in tis algo ... 
				}
				else
				{
					mark.at (tmp) = 'T';
				}
			}
		}
		for (int i = 0; i < xStr.size (); ++i)
		{
			if (mark.at (i) == 'F')
			{
				newX.push (current + xStr.substr (i, 1));
			}
		}
	}
	return -1; //  Impossible to get such an int
}

- meanmee November 24, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

//sort the array X in ascending order before calling this method.

bool rearrangeX(int*x, int* y, int size)
{
if (size == 0)
return true;
for (int i = 0; i < size; i++)
{
bool found = false;
if (x[0] >= y[0])
{
found = rearrangeX(x+1,y+1, size-1);
if (found)
return true;
}
if (i < size-1)
swap(x[i+1], x[0]);
}
return false;
}

- noname November 24, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

sort the array x in ascending order before calling this method

bool rearrangeX(int*x, int* y, int size)
{
	if (size == 0)
		return true;
	for (int i = 0; i < size; i++)
	{
		bool found = false;
		if (x[0] >= y[0])
		{
			found = rearrangeX(x+1,y+1, size-1);
			if (found)
				return true;
		}
		if (i < size-1)
			swap(x[i+1], x[0]);
	}
	return false;
}

- noname November 24, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

this is my solution in java

static int getClosestNumber(int[] x, int[] y) {
        int[] count = new int[10];
        for (int aX : x) {
            count[aX] += 1;
        }


        StringBuilder result = new StringBuilder();
        for (int aY : y) {
            // find maximum num
            for (int k = aY; k >= 0; k--) {
                if (count[k] > 0) {
                    result.append(k);
                    count[k] -= 1;
                    break;
                }
            }
        }

        for (int k = 9; k >= 0; k--) {
            if (count[k] > 0) {
                result.append(k);
                count[k] -= 1;
            }
        }

        return Integer.parseInt(result.toString());
    }

- skyisle November 27, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

What about the case x ={9,8,7,6,5,4,3,3,1}, y={2,2,2,2,2,2,2,2,2} ? Count Sort for x will be O(n) which is fine; however Binary Search for each element of y will be logn, logn + 1, logn + 2...logn + n-1, since at every occurrence of not finding 2 in x we will be traversing array x by one step to the right(i.e. ascending order). This gives a total time complexity of O(n) + (nlogn + n^2) which is O(n^2).

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

public boolean arrange(int[] x, int[] y)
{
   if(x.length != y.length)
      return false;
   else if(x.length == 0)
      return true;

   return arrHelper(x, y, 0);       
}

public boolean arrHelper(int[] x, int[] y, int p)
{
   if(p == x.length-1)
   {
       if(x[p] > y[p])
          return true;
       else
	  return false;
    }


   if(getEqual(x, y[p])
      return arrHelper(x, y, p+1);
   
   if(!getNext(x, y[p]))
      return false;
   Arrays.sort(p+1, x);
   return true;
}

public boolean getEqual(int[] x, int[] y, int p)
{
   for(int i = p; i < x.length; i++)
   {
       if(x[i] == y[p])
       {
           int h = x[i]; 
           x[i] = x[p];
	   x[p] = h;
	   return true;
       }
   }
   return false
}

public boolean getNext(int[] x, int[] y, int p)
{
   int min = Integer.MAX_VALUE;
   int j = p;
   int i = p;
   for(; i < x.length; i++)
   {
 	if(x[i] > y[p] && x[i] < min)
        {
 	   j = i;
           min = x[i];
        }
   }
   if(i == x.length) return false;
   int h = x[p];
   x[p] = x[j];
   x[j] = h;
   return true;
}

- panxin0718 January 27, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Start with the leftmost digit in y. If the digit exists in x, print it else print the next greatest.
y = 2410 x = 1234
2
4
1
3 // there is no zero, the next greatest unused digit is 3

- EK MACHCHAR May 22, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {
    char num[]="19999";
	char digits[]="12999";
	int dc[10];
	int n=5;
	char res[6];
	int i,j,k;
	memset(dc,0,sizeof(dc));
	for(i=0;i<n;i++) {
		dc[digits[i]-'0']++;
	}
	
	for(i=0;i<n;i++) {
		for(j=num[i]-'0';j<=9;j++) {
			if(dc[j]>0) {
				dc[j]--;
				res[i]=j+'0';
				break;
			}
		}
		if(j!=num[i]-'0')
			break;
	}
	
	if(j==10) {
		for(i--;i>=0;i--) {
			dc[res[i]-'0']++;
			for(j=res[i]-'0'+1;j<=9;j++) {
				if(dc[j]>0) {
					dc[j]--;
					res[i]=j+'0';
					break;
				}
			}
			if(j<=9)
				break;
		}
	}
	if(i==-1 || i==n) {
		printf("no such number\n");
		return 0;
	}
	for(k=0;k<=9 && i<n;k++) {
		for(j=0;j<dc[k];j++) {
			res[++i]=k+'0';
		}
	}

	res[n]='\0';
	printf("%s\n",res);
    
    return 0;
}

- hugakkahuga July 31, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Store x in an array and sort it. for each bit or element of y from right side find the bit or element in the array using binary search. if the element is present move it to the desired position in the array, now the length of the array will get reduced every time .If the element not present stop the algorithm, if the next element is grater than the bit which we are comparing then output the array it will give the number greater than y.

- Anonymous April 05, 2014 | Flag Reply


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