Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: Phone Interview




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

If it's an unweighted, undirectional graph then this can be done in O(N) (rather than O(N^2) for Djkstra) by simply doing a BFS traversal. You just keep looking through the nodes adjacent to any nodes you're currently examining that you haven't seen before until you see the node you're looking for, and then you reconstruct the path.

- Anonymous July 10, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
2
of 2 votes

And actually, it'll work for a directed graph as well... just as long as it's unweighted.

- Anonymous July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 votes

Here is the code, I'm not going to include the graph implementation but it's pretty easy to build one that provides what my graph does.

public static void findShortestPath(Graph g, int start, int stop)
	{
		g.getEdges(start);
		Queue <Integer> toVisit = new LinkedList<>();
		Set <Integer> alreadyVisited = new HashSet<>();

		Map <Integer, Integer> parent = new HashMap<>();
		alreadyVisited.add(start);
		toVisit.add(start);
		
		parent.put(start, null);
		while(!toVisit.isEmpty())
		{
			int cur = toVisit.poll();
			//We win
			if(cur == stop)
			{
				Integer at = cur;
				while(at != null)
				{
					System.out.print(at + ", ");
					at = parent.get(at);
				}
				return;
			}
			for(Edge e : g.getEdges(cur))
			{
				if(!alreadyVisited.contains(e.getVertexTo()))
				{
					parent.put(e.getVertexTo(), cur);
					alreadyVisited.add(e.getVertexTo());
					toVisit.offer(e.getVertexTo());
				}
			}
		}
		//We lose
		System.out.println("Couldn't find");
	}

- Anonymous July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Anonymous...nice code ...have some name...

- shsf July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

but question states that we have only two arguments start and end nodes
how can we take graph as another argument...

- Anonymous July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

It can be easily modify for that..

- shsf July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Even though we take two arguments, we still need to assume that we have some way to retrieve the adjacency list of every node. How else would you determine any path between two nodes? lol

- engineer July 22, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Really? Dijkstra's, straight out of the textbook?

- SGB July 09, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

No I think this must be BFS because there is no weights associated with it...And I am looking for some working code with the given parameters...

- AVK July 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is sample implementation of dijkstra's algorithm

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int q[100],rear,front;
int dist[100];

void enqueue(int data)
{
    int i,k;
    if(rear == -1)
    {
        rear = 0;
        front = 0;
        q[rear] = data;
    }
    else
    {
        for(i=0;i<rear+1;i++)
        {
            if(dist[data] >= dist[i])
            {
                continue;
            }
            else
            {
                for(k=rear;k>i;k--)
                {
                    q[k+1] = q[k];
                }
                q[i] = data;
                rear++;
                return;
            }
        }
        
    } 
}
    
int dequeue()
{
    int tmp;
    
    tmp = q[front];
    
    if(front == rear)
    {
        front = -1;
        rear = -1;
    }
    else
    {
        front++;
    }
    
    return tmp;

}



int  dijkstra(int **w,int n,int src)
{
    int i,alt;
    int u,v;
    
    for(i=0;i<n;i++)
    {
        dist[i] = 9999;
        enqueue(i);
    }
    
    dist[src] = 0;
    
    while(front != -1 && rear != -1)
    {
        u = dequeue();
        
        for(v=0;v<n;v++)
        {
            if(w[u][v] != 0)
            {
                alt = dist[u] + w[u][v];
                if(alt < dist[v])
                {
                    dist[v] = alt;
                    enqueue(v);
                }
            }
        }
    }
    
}
    
    

int main()
{
    int **weight;
    int max_node,i,j;
    int src;
    
    FILE * fin = fopen("input.txt","r");
    /* input file is "input.txt"
      eg.   4
            0 10 20 30
            0 0 5 15
            0 0 0 5
            0 0 0 0
    */
     
    weight = (int **)malloc(10*sizeof(int*));
    
    fscanf(fin,"%d",&max_node);
    for(i=0;i<max_node;i++)
    {
        weight[i] = (int *)malloc(10*sizeof(int));
    }
    
    
    for(i=0;i<max_node;i++)
    {
        for(j=0;j<max_node;j++)
        {
            fscanf(fin,"%d",&weight[i][j]);
            /* weight[i][j] = 0 if no path 
            between i and j */
        }
    }
    
    src = 0;
    
    dijkstra(weight,max_node,src);
    
    for(i=0;i<max_node;i++)
    {
        printf("\n %d",dist[i]);
    }
    /* sample output
      eg. 0
         10
         15
         20
    */
    
    return 0;
}

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

use minheap instead of the queue as:

int heap[100];
int top=0;

void enqueue(int data)
{
    int k;
    
    if(top == 0)
    {
        top = 1;
        heap[top] = data;
    }
    else
    {
        top++;
        k = top;
        
        while(dist[heap[k/2]] > dist[data] && k > 1)
        {
            heap[k] = heap[k/2];
            k = k/2;
        }
         
        heap[k] = data;
    }
}

int dequeue()
{
    int tmp,val,ind,j;
    int i,left,right;
    int flag = 0,count = 0;;
    
    tmp = heap[1];
    heap[1] = heap[top];
    heap[top] = tmp;
    
    tmp = heap[1];
    i =1;
    ind = i;
    
    while((2*i+1) < top && flag == 0)
    {
     flag = 1;
     left = 2*i;
     right = 2*i+1;
     
     if(dist[heap[left]] < dist[tmp] && left <= top)
     {
         ind = left;
     }
     
     if(dist[heap[right]] < dist[heap[ind]] && right <= top)
     {
         ind = right;
     }
     
     if(ind != i)
     {
         heap[i] = heap[ind];
         i = ind;
         flag = 0;
     }
    
    } 
    
    heap[i] = tmp;
     
    val = heap[top]; 
    top--;
   
    return val;
     
}

- jithin July 14, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is a C# implementation.

public class Vertex

{

    public string Id { get; set; }


    public List<Edge> Neighbours { get { return this.neighbours; } }

    private List<Edge> neighbours = new List<Edge>();

}


public class Edge

{

    public Vertex Target { get; set; }

    public int Cost { get; set; }

}


public class Graph

{

    public List<Vertex> Vertices { get { return this.vertices; } }

    private List<Vertex> vertices = new List<Vertex>();


public int ShortestPath(Vertex start, Vertex end, ref List<Vertex> path)

{

    // set initial distances

    Hashtable<Vertex, int> distances = this.InitializeDistances(start);


    // keep track of previous path

    Hashtable<Vertex, Vertex> previous = new Hashtable<Vertex, Vertex>();


    // process each vertex after adding them into a queue

    List<Vertex> queue = new List<Vertex> (this.Vertices);

    

    while (queue.Count > 0)

    {

        // get the vertex, which has the smallest distance, from the queue

        Vertex v = PopWithSmallestDistance (queue, distances);


int distanceV = distances [v];

if ( distanceV == Int32.Max) 

    break; // no edge or no need to continue


if ( v == end)

    break; // we are done


foreach ( Vertex n in v.Neighbours)

{

    int altN = distanceV + n.Cost;

    

    if ( altN < distances [n.Target] )        // relax

    {

        distances [n.Target] = altN;   // improve the result

        previous [n.Target] = v;         // add or override

}

}

}


// build up the path

Vertex temp = end;

while (temp != start)

{

    path.Add (temp);

    temp = previous [temp];

}


// add the initial vertex, too

path.Add (start);


// reverse the path

path.Reverse();


// return the shortest distance from start to end

return distances [end];

    }


private static Vertex PopWithSmallestDistance (

List<Vertex> queue, Hashtable<Vertex, int> distances)

{

    Vertex v = null;

    int min = Int32.Max;

    

    foreach ( Vertex t in queue)

    {

        int cost = distances [ t ];

        if ( cost < min )

        {

            v = t;

            min = cost;

}

}


queue.Remove (v);

return v;

}


    private Hashtable<Vertex, int> InitializeDistances (Vertex start)

    {

        Hashtable<Vertex, int> distances = new Hashtable<Vertex, int>();

        foreach (Vertex v in this.Vertices)

        {

            if (v != start)

            {

                // initial distance is inifite

                distances.Add(v, Int32.Max);

            }

            else

            {

                distances.Add (v, 0);

}

}


return distances;

}

}

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

package com.careercup.google;

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class ShortestPath {
static class Node
{
public ArrayList<Node> neighborNodes;
public int value;

public Node(int v)
{
neighborNodes = new ArrayList<Node>();
value = v;
}
}

static int traverse(Node node1, Node node2, LinkedHashSet<Node> traversedNodes, int knownLength, LinkedHashSet<Node> out)
{
int minLen = Integer.MAX_VALUE;
LinkedHashSet<Node> minPath = new LinkedHashSet<Node>();

if (!traversedNodes.contains(node1))
{
traversedNodes.add(node1);

if (!node1.equals(node2))
{
for (int i =0; i < node1.neighborNodes.size(); i++)
{
int len = traverse(node1.neighborNodes.get(i), node2, traversedNodes, knownLength + 1, out);
if (len < minLen)
{
minLen = len;
minPath.clear();
minPath.addAll(out);
}
}
}
else
{
minLen = knownLength + 1;
minPath.addAll(traversedNodes);
}

if (minPath.size() > 0)
{
out.clear();
out.addAll(minPath);
}

traversedNodes.remove(node1);
}

return minLen;
}

static void printResult(LinkedHashSet<Node> path) {
int i = path.size();
for (Node n : path)
{
System.out.print(n.value + ",");
}
}

/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1),
node2 = new Node(2),
node3 = new Node(3),
node4 = new Node(4),
node5 = new Node(5),
node6 = new Node(6),
node7 = new Node(7),
node8 = new Node(8),
node9 = new Node(9);

node1.neighborNodes.add(node2);
node2.neighborNodes.add(node5);
node5.neighborNodes.add(node6);
node6.neighborNodes.add(node8);

node2.neighborNodes.add(node6);

node1.neighborNodes.add(node3);
node3.neighborNodes.add(node4);
node4.neighborNodes.add(node8);

node1.neighborNodes.add(node5);
node5.neighborNodes.add(node6);
node6.neighborNodes.add(node8);


LinkedHashSet<Node> traversedNodes = new LinkedHashSet<Node>();
LinkedHashSet<Node> out = new LinkedHashSet<Node>();
int i = traverse(node1, node8, traversedNodes, 0, out);
if (i != Integer.MAX_VALUE)
{
printResult(out);
}
}

}

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

It think the hidden point in this question is "only the starting and the end nodes and nothing else". This implies that we are unsure about the wights. Algorithm such as Dijkstra cannot be a safe bet since it can't deal with negative weights. Furthermore, BFS is a good choice for finding the shortest path in a graph with unit weights edges. I think the better idea is to use the Bellman-Ford algorithm since it handles the shortest path regardless of the sign of the weight values and also checks if the graph has a negative-weight cycle in which case no all-pairs shortest paths (in case needed/asked) can be constructed.

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

asd

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

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class ShortestPath {
static class Node
{
public ArrayList<Node> neighborNodes;
public int value;

public Node(int v)
{
neighborNodes = new ArrayList<Node>();
value = v;
}
}

static int traverse(Node node1, Node node2, LinkedHashSet<Node> traversedNodes, int knownLength, LinkedHashSet<Node> out)
{
int minLen = Integer.MAX_VALUE;
LinkedHashSet<Node> minPath = new LinkedHashSet<Node>();

if (!traversedNodes.contains(node1))
{
traversedNodes.add(node1);

if (!node1.equals(node2))
{
for (int i =0; i < node1.neighborNodes.size(); i++)
{
int len = traverse(node1.neighborNodes.get(i), node2, traversedNodes, knownLength + 1, out);
if (len < minLen)
{
minLen = len;
minPath.clear();
minPath.addAll(out);
}
}
}
else
{
minLen = knownLength + 1;
minPath.addAll(traversedNodes);
}

if (minPath.size() > 0)
{
out.clear();
out.addAll(minPath);
}

traversedNodes.remove(node1);
}

return minLen;
}

static void printResult(LinkedHashSet<Node> path) {
int i = path.size();
for (Node n : path)
{
System.out.print(n.value + ",");
}
}

/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1),
node2 = new Node(2),
node3 = new Node(3),
node4 = new Node(4),
node5 = new Node(5),
node6 = new Node(6),
node7 = new Node(7),
node8 = new Node(8),
node9 = new Node(9);

node1.neighborNodes.add(node2);
node2.neighborNodes.add(node5);
node5.neighborNodes.add(node6);
node6.neighborNodes.add(node8);

node2.neighborNodes.add(node6);

node1.neighborNodes.add(node3);
node3.neighborNodes.add(node4);
node4.neighborNodes.add(node8);

node1.neighborNodes.add(node5);
node5.neighborNodes.add(node6);
node6.neighborNodes.add(node8);


LinkedHashSet<Node> traversedNodes = new LinkedHashSet<Node>();
LinkedHashSet<Node> out = new LinkedHashSet<Node>();
int i = traverse(node1, node8, traversedNodes, 0, out);
if (i != Integer.MAX_VALUE)
{
printResult(out);
}
}

}

- Anonymous July 04, 2019 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

If you downvote any question please put reasons...it would serve as guideline to people who are going to post any new questions..else there is no meaning...In this questions I guess downvote is for not describing the graph type properly..

(or downvoted because question is very simple ???? it is simple if you have a lot of time...)

- shsf July 10, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Too textbook, and not clear (weighted edges, or not?)

- SGB July 13, 2013 | 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