Google Interview Question for Developer Program Engineers


Country: United States




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

Either they wanted an open ended discussion or you omitted something. If the task is to compress a completely random string of bits there is no loss less algorithm possible.
if all combinations of 1s a and 0s are possible and all are equally likely then you are stuck. You have 2^n possible states so you need log2(2^n) to store it.
If less than 2^(n-1) states are possible you can send enough bits to reconstruct the n bits in less than n bits.
If some states are common and others are uncommon you can compress to a variable length string. Say 2^(n-m) states happen x fraction of the time then you can put one bit at the front if it is one you sent the compressed version taking 1 + log2(2^(n-m) x of the time.
If it is an unusual sequence in the (1-x) portion of the probability space you set the first bit the other way and send 1+log2(2^n) bits.
You only need a few bits to send the common sequences and the same number to send the uncommon ones but you need 1 bit extra to specify which regime you are in.
On average you will send 1 + log2(2^(n-m) x + 1+log2(2^n)(x-1) bits or
1+(n-m) * x + n * (x-1) if x is close to 1 you are in luck.
Generally compression algorithms look at small portions of the file at a time and different combinations of bits have a wide variety of distributions. If you were compressing English on a letter by letter basis you would find that for most texts e and a is more common than x and q. You could compress on the word basis or even compress phrases. You might compress the file by turning it into a list of numbers referring to a dictionary of English words. You could throw all letters into the dictionary so that you can spell out words when you run into words you can’t find in your dictionary. Obviously if you were using 16 or 24 bit numbers to index into your word dictionary, when you hit words you have to spell out you would use more space when if you had just spelled everything out with 8 bit letters. But you would save space when compressing longer words.
Huffman coding is a similar algorithm that is much more general and generally more efficient but harder to explain here.
Depending on the type of data you are compressing both the compressor and decompressor will need a dictionary of some kind. Often the advantages of coming up with a custom dictionary for the particular file are so great it makes sense to append the dictionary as part of the compressed file rather than using a dictionary you store in the programs themselves though.
Other documents and messages have other patterns.
Bit map images of line drawings for instance can be compressed using essentially an algorithmic dictionary. An algorithm called run length encoding describes the document in terms of how many pixels are black and then how many pixels are white as you raster across the image.
Computer languages of course will often have very limited vocabularies and grammars that can permit other specialized compression techniques.
I believe general purpose compressors will try a number of approaches and then go with the best one. I think some algorithms may try a lossy algorithm and then compute the errors and try to compress them though I am not certain if this is actually used for lossless compression.

- Dr ADM May 12, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I completely agree. Pure random data would not be losslessly compressible. However, I hadn't thought the data was random because that was never mentioned in the subject. But, if it were perfectly random then I'm not sure someone would really want to send it. I could only think of a few things that pure random data could be- a 1 time pad or some observed natural phenonemon... ?

- zortlord May 19, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

it could be compressed data

- DR A.D.M May 27, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 3 vote

///
//////////////////////////////////////////////////////////////
///
/// Time : O(n) n = number of elements.
/// Space: O(n).
//
//////////////////////////////////////////////////////////////
//
#define MAX(a,b) (a>b ? a: b)
/// go over the array from left to right and from right to left.
/// take the maximum of the computed array. This is necessary as
/// the maximum is needed to accomdate the longest increasing or
/// decreasing sequence.
///
/// if current element is bigger than the next element. restart from
/// 1. the reverse order will catch what the next element should be.
int get_min_candy(int *a, int size) {
int lr[size], rl[size];
int sum = 0;
for (int i=0;i<size;++i) {
lr[i] = rl[i] = 1;
}

for (int i=0;i<size-1;++i) {
if (a[i] < a[i+1])
lr[i+1] = lr[i]+1;
}

for (int i=size-1;i>0;--i) {
if (a[i] < a[i-1])
rl[i-1] = rl[i]+1;
}

for (int i=0;i<size;++i) {
sum += MAX(lr[i], rl[i]);
}

return sum;
}

//////////////////////////////////////////////////////////////
// main.
//////////////////////////////////////////////////////////////
int main() {
int a[] = {2,6,1,2,9,1,1,4,9,6,3,5,1};
printf("%d\n", get_min_candy(a, sizeof(a)/sizeof(a[0])));
return 0;
}
\\\

- Xin Tong May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sounds great so far.
can we optimize it to avoid lr lookup O(n) + rl lookup O(n) + find higher O(n)
into single lookup and thats it. that array can be final answer
hint: both time we traverse through same length of array

- geegygeek May 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi can you explain your solution a little more or give any wiki of the theory ?

- um01 May 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think we could. but I feel the way it's written is more clear.

- Anonymous May 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

can you explain what this has to do with compressing a stream of bytes?

- Code ka mogambo May 17, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The original question is about a stream of 1 and 0 and when you say stream i guess we are not talking about the classic compression algorithm here.

Also the program you have written, first you should provide subjective description of the solution rather jumping directly into the coding which most of the interviewer don't like

- pc June 02, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

//////////////////////////////////////////////////////////////
/// solution 1.
///
/// Time : O(n) n = number of elements.
/// Space: O(n).
//
//////////////////////////////////////////////////////////////
//
#define MAX(a,b) (a>b ? a: b)
/// go over the array from left to right and from right to left.
/// take the maximum of the computed array. This is necessary as
/// the maximum is needed to accomdate the longest increasing or
/// decreasing sequence.
///
/// if current element is bigger than the next element. restart from
/// 1. the reverse order will catch what the next element should be.

int get_min_candy(int *a, int size) {
    int lr[size], rl[size];
    int sum = 0;
    for (int i=0;i<size;++i) {
        lr[i] = rl[i] = 1;
    }

    for (int i=0;i<size-1;++i) {
        if (a[i] < a[i+1])
           lr[i+1] = lr[i]+1;
    }

    for (int i=size-1;i>0;--i) {
        if (a[i] < a[i-1])
           rl[i-1] = rl[i]+1;
    }

    for (int i=0;i<size;++i) {
        sum += MAX(lr[i], rl[i]);
    }

    return sum;
}

//////////////////////////////////////////////////////////////
// main.
//////////////////////////////////////////////////////////////
int main() {
    int a[] = {2,6,1,2,9,1,1,4,9,6,3,5,1};
    printf("%d\n", get_min_candy(a, sizeof(a)/sizeof(a[0])));
    return 0;
}

- Xin Tong May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

//////////////////////////////////////////////////////////////
/// solution 1.
///
/// Time : O(n) n = number of elements.
/// Space: O(n).
//
//////////////////////////////////////////////////////////////
//
#define MAX(a,b) (a>b ? a: b)
/// go over the array from left to right and from right to left.
/// take the maximum of the computed array. This is necessary as
/// the maximum is needed to accomdate the longest increasing or
/// decreasing sequence.
///
/// if current element is bigger than the next element. restart from
/// 1. the reverse order will catch what the next element should be.
int get_min_candy(int *a, int size) {
    int lr[size], rl[size];
    int sum = 0;
    for (int i=0;i<size;++i) {
        lr[i] = rl[i] = 1;
    }

    for (int i=0;i<size-1;++i) {
        if (a[i] < a[i+1])
           lr[i+1] = lr[i]+1;
    }

    for (int i=size-1;i>0;--i) {
        if (a[i] < a[i-1])
           rl[i-1] = rl[i]+1;
    }

    for (int i=0;i<size;++i) {
        sum += MAX(lr[i], rl[i]);
    }

    return sum;
}

//////////////////////////////////////////////////////////////
// main.
//////////////////////////////////////////////////////////////
int main() {
    int a[] = {2,6,1,2,9,1,1,4,9,6,3,5,1};
    printf("%d\n", get_min_candy(a, sizeof(a)/sizeof(a[0])));
    return 0;
}

- trent.tong May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class AssignChocolates {

public int[] assignChocolates(int[] ages) {
int[] assign = new int[ages.length];
for (int i = 0; i < ages.length; i++) {
assign[i] = 1;
}
for (int i = 1; i < ages.length; i++) {
if (ages[i] > ages[i-1]) {
assign[i] = assign[i-1] + 1;
}
}
for (int i = ages.length-2; i >= 0; i--) {
if (ages[i] > ages[i+1]) {
assign[i] = assign[i+1] + 1;
}
}
return assign;
}

/**
* @param args
*/
public static void main(String[] args) {
int[] ages = new int[]{2, 6, 1, 3, 2, 1, 9};
AssignChocolates c = new AssignChocolates();
int[] assign = c.assignChocolates(ages);
for (int i = 0; i < assign.length; i++) {
System.out.print(assign[i] + " ");
}
}
}

- Anonymous May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class AssignChocolates {

	public int[] assignChocolates(int[] ages) {
		int[] assign = new int[ages.length];
		for (int i = 0; i < ages.length; i++) {
			assign[i] = 1;
		}
		for (int i = 1; i < ages.length; i++) {
			if (ages[i] > ages[i-1]) {
				assign[i] = assign[i-1] + 1;
			}
		}
		for (int i = ages.length-2; i >= 0; i--) {
			if (ages[i] > ages[i+1]) {
				assign[i] = assign[i+1] + 1;
			}
		}
		return assign;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] ages = new int[]{2, 6, 1, 3, 2, 1, 9};
		AssignChocolates c = new AssignChocolates();
		int[] assign = c.assignChocolates(ages);
		for (int i = 0; i < assign.length; i++) {
			System.out.print(assign[i] + " ");
		}
	}

}

- peter May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

It takes 2 hours, is it ok?

int[] age = new int[13] { 2, 6, 1, 2, 9, 1, 1, 4, 9, 6, 3, 5, 1 };
            int[] choco = new int[13];
            int descendingLength;
            for (int i = 0; i < age.Length; i++)
            {
                if (i < age.Length - 1)
                {
                    if (age[i] > age[i + 1])
                    {
                        descendingLength = 1;
                        int j;
                        for (j = i; (j + 1) < age.Length && age[j] > age[j + 1]; j++)
                            descendingLength++;
                        if(i != 0 && choco[i-1] >= descendingLength)
                        {
                            if (age[i-1] == age[i])
                                choco[i] = choco[i - 1];
                            else
                                choco[i] = choco[i - 1] + 1;
                            i++;
                            descendingLength--;
                        }
                        while (descendingLength > 0)
                        {
                            choco[i] = descendingLength--;
                            i++;
                        }
                        i--;
                    }
                    else
                        if (i != 0 && age[i] > age[i - 1])
                            choco[i] = choco[i - 1] + 1;
                        else
                            choco[i] = 1;
                }
                else
                {
                    if (age[i] > age[i - 1])
                        choco[i] = choco[i - 1] + 1;
                    else
                        choco[i] = 1;
                }
            }
            foreach (int col in choco)
                Console.Write(col + " ");

- ulmaxy May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It was a wrong way to do it, here is the proper:

static void Main(string[] args)
        {
            int[] age = new int[13] { 2, 6, 1, 2, 9, 1, 1, 4, 9, 6, 3, 5, 1 };
            int[] choco = new int[13];
            int descendingLength;
            for (int i = 0; i < age.Length; i++)
            {
                if (i < age.Length - 1)
                {
                    if (age[i] > age[i + 1])
                    {
                        descendingLength = 1;
                        int j;
                        for (j = i; (j + 1) < age.Length && age[j] > age[j + 1]; j++)
                            descendingLength++;
                        if (i != 0 && choco[i - 1] >= descendingLength)
                        {
                            if (age[i - 1] == age[i])
                                choco[i] = choco[i - 1];
                            else
                                choco[i] = choco[i - 1] + 1;
                            i++;
                            descendingLength--;
                        }
                        while (descendingLength > 0)
                        {
                            choco[i] = descendingLength--;
                            i++;
                        }
                        i--;
                    }
                    else
                        if (i != 0 && age[i] > age[i - 1])
                            choco[i] = choco[i - 1] + 1;
                        else
                            choco[i] = 1;
                }
                else
                {
                    if (age[i] > age[i - 1])
                        choco[i] = choco[i - 1] + 1;
                    else
                        choco[i] = 1;
                }
            }
            foreach (int col in choco)
                Console.Write(col + " ");
        }

- ulmaxy May 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

How's about implementing a series of compression algorithms (huffman, chunking, etc), each prefixing the encoding header information in a parseable way (IE: encrypting 'Message' with chunking -> [header:chunking]+chunking('Message') ) Using each of these algorithms, you could effectively search the space of all possible encoding applications to optimize the size of the message regardless the computational complexity. Convert the problem into a search problem. True, it would be EXTREMELY computationally expensive, but it would probably optimize the size of the message.

- zortlord May 12, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This would work great if you were not sending totally random data. But if you were sending totally random data you would not be able to compress it.
Let's say you had an algorithm that could compress totally random data into something smaller all the time. The resulting stream of bits would be totally random. So you would be able to compress it and so on until you only had 1 bit left.
Or think about in another way say I could send you one of 8 messages but they were 8 bytes long. We could agree on a code and I could send you 3 bits and then you could decode them. This would be great. But now say I could send you 2^(8*8) messages or all possible values of the 8 bytes well we would be out of luck. As there would need log2(2^(8*8)) = 8*8 bits required to specify which code I wanted to send.
This idea comes out of the field of information theory.
I have heard it postulated that alien civilizations that are reasonably advanced will send everything in a compressed from and as a result you won't be able to spot the pattern as the data will be totally random to those that don’t have the right codec. It is a bit more complex then that but basically once you compress it enough it becomes a totally random all patterns are possible and all are equally likely.
It is a nice concept and can help you think about it I wish I could explain it better it has helped me greatly.

- Dr A.D.M. May 14, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.Stack;



class test{
public class InorderIterator {
Stack<Node> st = new Stack<Node>();
Node root;
Node nextNode = null;

public InorderIterator(Node root) {
this.root = root;
}

public boolean hasnext(){
if(nextNode != null) return true;
Node cur = null;
if(st == null) return false;
if(!st.empty())
cur = st.pop();
else{
cur = root;
}
while(true){
if(cur != null){
st.push(cur);
cur = cur.left;
}else{
if(!st.isEmpty()){
Node tmp = st.pop();
if(nextNode == null){
nextNode = tmp;
}
st.push(tmp.right);
tmp = tmp.right;
return true;
}else{
st= null;
return false;
}
}
}
}

public Node next(){
if(nextNode != null){
Node tmp = nextNode;
nextNode = null;
return tmp;
}
if(hasnext()){
Node tmp = nextNode;
nextNode = null;
return tmp;
}else{
new Exception("Element not found");
}

return nextNode;
}
}

class Node{

Node right;
Node left;
char value;
Node(){
this.left=null;
this.right=null;
}
}

public boolean sameInorder(Node root1,Node root2){
InorderIterator itr1 = new InorderIterator(root1);
InorderIterator itr2 = new InorderIterator(root2);
System.out.println(itr1.next());
while(itr1.hasnext() && itr2.hasnext()){
if(itr1.next().value != itr2.next().value){
return false;
}
}
if((!itr1.hasnext() && itr2.hasnext()) || (itr1.hasnext() && !itr2.hasnext())){
return false;
}
return true;
}

public static void main(String[] args){
test t=new test();
Node firstroot=t.new Node();
Node secondroot=t.new Node();
Node left=t.new Node();
Node right=t.new Node();
left.value='A';
right.value='C';
firstroot.value='B';
firstroot.left=left;
firstroot.right=right;
secondroot.value='A';
secondroot.left=null;
Node right1=t.new Node();
secondroot.right=right1;
right1.value='B';
Node right2=t.new Node();
right1.right=right2;
right2.value='C';

System.out.println(t.sameInorder(firstroot,secondroot));


}

}

- sai April 03, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.Stack;



class test{
public class InorderIterator {
	Stack<Node> st = new Stack<Node>();
	Node root;
	Node nextNode = null;
	
	public InorderIterator(Node root) {
		this.root = root;
	}

	public boolean hasnext(){
		if(nextNode != null) return true;
		Node cur = null;
		if(st == null) return false;
		if(!st.empty())
			cur = st.pop();
		else{
			cur = root;
		}
		while(true){
			if(cur != null){
				st.push(cur);
				cur = cur.left;
			}else{
				if(!st.isEmpty()){
					Node tmp = st.pop();
					if(nextNode == null){
						nextNode = tmp;
					}
					st.push(tmp.right);
					tmp = tmp.right;
					return true;
				}else{
					st= null;
					return false;
				}
			}
		}
	}
	
	public Node next(){
		if(nextNode != null){
			Node tmp = nextNode;
			nextNode = null;
			return tmp;
		}
		if(hasnext()){
			Node tmp = nextNode;
			nextNode = null;
			return tmp;
		}else{
			new Exception("Element not found");
		}
		
		return nextNode;
	}
}

class Node{
	
	Node right;
	Node left;
	char value;
	Node(){
		this.left=null;
		this.right=null;
	}
}

public  boolean sameInorder(Node root1,Node root2){
    	   	InorderIterator itr1 = new InorderIterator(root1);
    	   	InorderIterator itr2 = new InorderIterator(root2);
    	   	System.out.println(itr1.next());
	   		while(itr1.hasnext() && itr2.hasnext()){
	   			if(itr1.next().value != itr2.next().value){
	   				return false;
	   			}
	   		}
	   		if((!itr1.hasnext() && itr2.hasnext()) || (itr1.hasnext() && !itr2.hasnext())){
	   			return false;
	   		}
	   		return true;
       }

public static void main(String[] args){
	test t=new test();
	Node firstroot=t.new Node();
	Node secondroot=t.new Node();
	Node left=t.new Node();
	Node right=t.new Node();
	left.value='A';
	right.value='C';
	firstroot.value='B';
	firstroot.left=left;
	firstroot.right=right;
	secondroot.value='A';
	secondroot.left=null;
	Node right1=t.new Node();
	secondroot.right=right1;
	right1.value='B';
	Node right2=t.new Node();
	right1.right=right2;
	right2.value='C';
	
	System.out.println(t.sameInorder(firstroot,secondroot));
	
			
}

}

- sai April 03, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Following is my solution in O(n):

/**
 * Created by sky on 5/11/15.
 */
public class DistributeChocolate {

    public static void main(String[] args) {
        int[] kids = new int[] {2, 6, 1, 2, 9, 1, 1, 4, 9, 6, 3, 5, 1};
        int[] choco = new int[kids.length];

        int saved = 1;
        for (int i = 0; i < kids.length; i++) {
            if (i == 0) {
                choco[i] = saved;
                continue;
            }

            if (kids[i] <= kids[i - 1]) {
                saved = 1;
                choco[i] = saved;
            } else {
                choco[i] = ++saved;
            }
        }

        for (int i = 0; i < choco.length; i++) {
            if (i > 0) System.out.print(" ");
            System.out.print(choco[i]);
        }
        System.out.println();
    }
}

- Felipe Cerqueira May 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Appreciate your effort BUT,
please try with below input which is violating law.
kids : 2, 6, 1, 3, 2, 1, 9
choc: 1, 2, 1, 2, 1, 1, 2
2nd kid of age 2 years should get more than younger(1 year) next to him
please try

- geegygeek May 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

What is the problem are you solving?

- Sergey May 14, 2015 | Flag


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