Google Interview Question for Software Engineer / Developers






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

The best solution is O(n + m) using a generalized suffix tree (GST) of all strings (along each row and along each column). Here n = length of all strings in puzzle (both along each row and along each column) and m = length of word which we need to find. For word w, scan the GST tree. For circular string, if word w is present till ith character then follow the 'pth row'/'qth col' corresponding to that leaf node in GST tree and see whether remaining characters in word are present in original char matrix's 'pth row'/'qth col'.

It may appear complicated, but once you understand how suffix trees (http://en.wikipedia.org/wiki/Suffix_tree) and generalized suffix trees (http://en.wikipedia.org/wiki/Generalised_suffix_tree) are, it will seem pretty trivial.

- Gopal Krishna August 13, 2009 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Looks pretty similar to FloodFill() in image processing. Recursion is needed to do job.

btw, can a word be represented in diagonally connected? Be clear, is 4-neighbor or 8-neighbor or even not on a straight line?

- letsgo September 18, 2008 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yup the solution can be solved by using recursion. i dont know much optimised code other than this. for evry position (i,j) there are total 8 directions possible in which we can move. Scanning in each directions keeping track of in which base direction we are moving and checking boundary conditions . and updating the same

- backtolife September 19, 2008 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Not a completely correct program..

package google;

import java.util.ArrayList;
import java.util.HashMap;

public class CrossWord {

//private char [][] puzzle;
private ArrayList<String> puzzle = new ArrayList<String>();
private HashMap<String,Integer> myMap = new HashMap<String,Integer>();

public CrossWord(){
puzzle.add("aerops");
puzzle.add("bharls");
puzzle.add("wrislo");
puzzle.add("asnktq");
}

private void createHashMap(){
int i = 0;

int row = 0;
int col = 0;

while(i < puzzle.size()){
String key = getWord(i,-1);
myMap.put(key,0);
i++;
}
while (col < (puzzle.get(row).length() )){
String key = getWord(-1, col);
myMap.put(key,0);
col++;
}

}

private String getWord(int row ,int col){
char[][] puzzleArr = null;
String tempo = null;
String temp = null;


if(row >= 0 && row < puzzle.size()){
temp = puzzle.get(row);
row++;
}

else{
if(col >= 0){
for(int i = 0; i < puzzle.size() ; i++){
char[] temp1= puzzle.get(i).toCharArray();
Character c = temp1[col];
tempo += (c.toString());
}
String correctWord = tempo.substring(4);
return correctWord;
}
}
return temp;

}

public void display(){
System.out.println(myMap.keySet().toString());
}

public void isPresent(String word){
if(myMap.keySet().contains(word)){
System.out.println("Found!");
}
else{
System.out.println("Not Found!");
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

CrossWord obj = new CrossWord();
obj.createHashMap();
obj.isPresent("slow");
}
}

- Java Coder October 10, 2008 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Humans have languages like English.

- Mahesh April 15, 2010 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

floodfill is not really gonna work here.. as we dont have to go on and test every neighbouring element once we have a 2 char match. We need to look for only vertical horizontal or diagonal letters in the matrix. Tho an algo much similar to floodfill wud b d sol..

- aks October 20, 2008 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I agree with Rohith menon solution

- Mohan December 08, 2008 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

@Gopal Krishana
I completely agree with your solution. That's the first thing i thought of after going through the question...

- googler August 20, 2009 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

@Gopal Krishana
I completely agree with your solution. That's the first thing i thought of after going through the question...

- googler August 20, 2009 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

what about columns in the above approach?

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

Is it boggle game problem? I think like 8 queen problem, we should use recursion and backward tracking.

- xyz November 15, 2009 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

My solution (intentionally) looks all 4 ways to search for the word, not just left->right and up-> down

public void FindAWordInPuzzleStart()
        {
            char[,] puzzle = { { 'a', 'e', 'r', 'o', 'p', 's' }, 
                             { 'b', 'h', 'a', 'r', 'l', 's' }, 
                             { 'w', 'r', 'i', 's', 'l', 'o' }, 
                             { 'a', 's', 'n', 'k', 't', 'q' } };
            string[] searchWords = new string[] { "rain", "bha", "ropa", "rainr", "rops", "abz", "abw", "123456", "1234567" };
            Console.WriteLine("Puzzle:");
            int lengthDim2 = puzzle.GetLength(1);
            for (int i = 0; i < puzzle.Length; i++)
            {

                Console.Write(puzzle[i/lengthDim2, i%lengthDim2]);
                if (i%lengthDim2 == lengthDim2-1)
                    Console.WriteLine();
            }
            Console.WriteLine();
            foreach (string searchWord in searchWords)
            {
                Console.WriteLine("Searching for \"" + searchWord + "\": " + FindAWordInPuzzle(searchWord.ToCharArray(), 0, puzzle, -1, -1).ToString());
            }
            


        }

        private bool FindAWordInPuzzle(char[] word, int startIndex, char[,] puzzle, int currentSearchLoc, int searchDirection)
        {
            if (word == null || word.Length < 1 || puzzle.Length < 1)
                throw new ArgumentException();
            int lengthDim1 = puzzle.GetLength(0),
                lengthDim2 = puzzle.GetLength(1),
                x,
                y,
                nextX,
                nextY;

            //word too big to fit into the puzzle
            if (word.Length > lengthDim1 && word.Length > lengthDim2)
                return false;
            if (startIndex < 1)
            {
                //startIndex = 0;
                for (int i = 0; i < puzzle.Length; i++)
                {
                    x = i / lengthDim2;
                    y = i % lengthDim2; //always positive since i is positive

                    if (word[0] == puzzle[x, y])
                    {
                        //startIndex++;
                        if (word.Length == 1)
                            return true;
                        if (word.Length <= lengthDim2)
                        {
                            nextY = (y - 1) % lengthDim2;
                            while (nextY < 0)
                                nextY += lengthDim2;
                            if (FindAWordInPuzzle(word, 1, puzzle, x * lengthDim2 + nextY, -1))
                                return true;
                            nextY = (y + 1) % lengthDim2;
                            if (FindAWordInPuzzle(word, 1, puzzle, x * lengthDim2 + nextY, +1))
                                return true;
                        }
                        if (word.Length <= lengthDim1)
                        {
                            nextX = (x - 1) % lengthDim1;
                            while (nextX < 0)
                                nextX += lengthDim1;
                            if (FindAWordInPuzzle(word, 1, puzzle, nextX * lengthDim2 + y, -lengthDim2))
                                return true;

                            nextX = (x + 1) % lengthDim1;
                            if (FindAWordInPuzzle(word, 1, puzzle, nextX * lengthDim2 + y, +lengthDim2))
                                return true;
                        }
                    }

                }
                return false;
            }
            else
            {
                currentSearchLoc = currentSearchLoc % puzzle.Length;
                while (currentSearchLoc < 0) //make it positive
                    currentSearchLoc += puzzle.Length;

                x = currentSearchLoc / lengthDim2;
                y = currentSearchLoc % lengthDim2; //always positive since currentSearchLoc is guaranteed positive above

                if (word[startIndex] == puzzle[x, y])
                {

                    startIndex++;
                    
                    //if the last character has just been compared, then we found it, return true.
                    if (startIndex == word.Length)
                        return true;

                    if (searchDirection == -1 || searchDirection == +1)
                    {
                        nextY = (y + searchDirection) % lengthDim2;
                        while (nextY < 0)
                            nextY += lengthDim2;
                        return FindAWordInPuzzle(word, startIndex, puzzle, x * lengthDim2 + nextY, searchDirection);
                    }
                    else
                    {
                        nextX = (currentSearchLoc + searchDirection) % puzzle.Length;
                        while (nextX < 0)
                            nextX += puzzle.Length;
                        return FindAWordInPuzzle(word, startIndex, puzzle, nextX, searchDirection);
                    }
                }
                else return false;

            }

        }

- Oz November 28, 2009 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Will Trie not solve this, I think trie cab be helpful

- erappy July 01, 2010 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This problem can be solved in O(M+N). Obviously we have to use recursion.

Call a function for row and column recursively . The function can be terminated when length of word will be traverse completely.
If the first character of word will match with puzzle matrix then we go call recursively either in direction of row or column. and it will be continue till the end(word search complete)

NOTE : I'm considering only 4 direction ( L->R, R->L,T->B,B->T). This solution can be extended for diagonal checking also.

Comments are most welcome.

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

After looking at the problem I thought its not that difficult but I had like 5-6 bugs in my implementation and it took around 2 hours to get this code.

Idea is for each element in matrix find if it matches the first word, if it matches then we have to look in 4 directions. If there is match in that direction proceed till we are end of the string. If match return true if not return false. We have or || all the directions because the string can be in any of 4 directions. Also Math.abs takes care of wrap around (this was my big bug)

package com.code.prolificcoder;

public class StringFinder {
	enum Direction{up,down,left,right};
	public static void main(String args[]){
		char[][] ar=new char[][]{{'m','s','s','h'},
								 {'a','t','c','i'},
								 {'p','d','a','n'},
								 {'s','a','t','h'},
								};
		String str="tcia";
		StringFinder sf=new StringFinder();
		System.out.print(sf.stringFinder(ar,str));
		}

	private boolean stringFinder(char[][] ar, String str) {
		int size=ar.length;
		if(str.length()>size+1) return false;
		int k=0; 
		char[] charArray=str.toCharArray();
		for(int i=0;i<size;i++)
			for(int j=0;j<size;j++)
				if(ar[i][j]==charArray[k])
					return isMatch(ar,charArray,i,Math.abs((j+1)%size),k+1,Direction.right)||
					isMatch(ar,charArray,Math.abs((i+1)%size),j,k+1,Direction.down)||
					isMatch(ar,charArray,Math.abs((i-1)%size),j,k+1,Direction.up)||
					isMatch(ar,charArray,i,Math.abs((j-1)%size),k+1,Direction.left);
		return false;
	}

	private boolean isMatch(char[][] ar, char[] charArray, int i, int j, int k, Direction dir) {
		int size=ar.length;
		if(k==charArray.length-1)
		{
			if(ar[i][j]==charArray[k]) return true;
			else return false;
		}
		if(ar[i][j]==charArray[k]){
			if(dir==Direction.down)
				i=Math.abs((i+1)%size);	
			else if(dir==Direction.right)
				j=Math.abs((j+1)%size);	
			else if(dir==Direction.left)
				j=Math.abs((j-1)%size);
			else //dir==Direction.up
				i=Math.abs((i-1)%size);
		
			return isMatch(ar,charArray,i,j,k+1,dir);
		}
		
		
		return false;
	}

	
	
}

- prolific.coder August 10, 2010 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This is a simple question. To write bug free code is not that simple.
The secret is to use abstraction; don't write messy code in one big function. In real interviews the code typically just has no more than 20 lines.

For this problem I will first define the following data structures:

enum Direction {
    UP, DOWN, LEFT, RIGHT;
}

class Point {
    // returns false if unable to go to that direction
    // otherwise move the current point to new position
    public boolean go(Maze maze, Direction dir);
}

class Maze implements Iterable<Point> {
    public Iterator<Point> iterator();
    public char get(Point point);
}

And here is the code, just a few lines:

public static boolean exists(Maze maze, String word) {
    if (word.length() == 0) return true;
    char firstChar = word.charAt(0);
    for (Point point : maze) {
        char ch = maze.get(point);
        if (ch == firstChar && exists(maze, point, word, 1))
            return true;
    }
    return false;
}

private static boolean exists(Maze maze, Point point, String word, int index) {
    if (index == word.length() - 1) return true;
    char ch = word.charAt(index);
    for (Direction dir : Direction.values()) {
        if (point.go(maze, dir)        
            && maze.get(point) == ch)
            && exists(maze, point, word, index + 1))
                 return true;
    }
    return false;
}

By providing a few lines of code, the chances of getting bugs are low.

Then, next step is to implement each functions if the interviewer asks.

- Ryan August 25, 2010 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I would create two longs strings scanning the table horizontally first and then for the second scan it vertically. Search for rain or niar for example in either string.

- dantepy May 15, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

boolean search(char[][] matrix, int m, int n, char[] str)
{
if (str == null) return true;

for (int i = 0; i < m; i ++)
{
for( int j = 0; j < n; j ++)
{
boolean hit = false;
if (matrix[i][j] == str[0])
{
if (subsearch(matrix, m, n, str, strlen(str), 1, j, i, 0) return true;
if (subsearch(matrix, m, n, str, strlen(str), 1, j, i, 1) return true;
if (subsearch(matrix, m, n, str, strlen(str), 1, j, i, 2) return true;
if (subsearch(matrix, m, n, str, strlen(str), 1, j, i, 3) return true;
}
}
}

return false;
}

boolean subsearch(char[][] matrix, int m, int n, char[] str, int len, int loc, int curx, int cury, int direction)
{
if (loc == len) return true;

if (direction == 0) // go right
{
curx ++;
if (curx == m)
{
curx = 0;
cury ++;
if (cury >= n) return false;
}
}
else if (direction == 1) //go down
{
cury ++;
if (cury == n)
{
cury = 0;
curx ++;
if (curx >= m) return false;
}
}
else if (direction == 2) //go left
{
curx --;
if (curx == -1)
{
curx = m - 1;
cury --;
if (cury < 0) return false;
}
}
else //go up
{
cury --;
if (cury == -1)
{
cury = n - 1;
curx --;
if (curx < 0) return false;
}
}

if (matrix[curx][cury] == str[loc])
{
return subsearch(matrix, m, n, str, len, loc + 1, curx, cury, direction)
}

return false;
}

- li June 23, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

If the 2d array size was NxM create another array of size (2N x 2M). Copy the array 4 times in each block. Now the word should be present in the big array without wrap. Scan row and find the word. If not found scan column and find the word. If not found the word is not present.

- Joy June 24, 2016 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.ArrayList;

/**
 * Created by poorvank on 15/08/16.
 */
public class StringPuzzle {

    private static int row, col;

    //Traversing in all 4 directions
    private static int x[] = {0, 1, -1,  0};
    private static int y[] = {1, 0,  0, -1};


    public static boolean find(String toFind, Character[][] puzzle) {

        row = puzzle.length;
        col = puzzle[0].length;

        boolean[][] visited = new boolean[row][col];
        for (int j = 0; j < col; j++) {
            for (int i = 0; i < row; i++) {
                if ((puzzle[i][j] == toFind.charAt(0)) && !visited[i][j]) {

                    if (findUtil(toFind, puzzle, i, j, visited, new StringBuilder(), 0,new ArrayList<>())) {
                        return true;
                    }
                    visited[i][j] = false;
                }
            }
        }

        return false;

    }


    private static boolean findUtil(String toFind, Character[][] puzzle, int i, int j, boolean[][] visited, StringBuilder sb, int index, ArrayList<String> list) {

        sb.append(puzzle[i][j]);
        //List used to print path when a string is found
        list.add("(" + i+ "," + j +")");
        if (sb.toString().equals(toFind)) {

            System.out.println("Path is = " + list.toString());
            return true;
        }
        if(index==toFind.length()) {
            return false;
        }

        visited[i][j] = true;
        int nextIndex = index + 1;
        int nextR, nextC;

        for (int k = 0; k < 4; k++) {

            nextR = i + x[k];
            nextC = j + y[k];

            if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

            }

            //Checking Wrap Around cases
            //Corner Cases
            if ((i == 0 && j == 0) || (i == row - 1 && j == col - 1)) {
                nextR = row - 1;
                nextC = 0;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }

                nextR = 0;
                nextC = col - 1;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }


            } else if ((i == 0 && j == col - 1) || (i == row - 1 && j == 0)) {
                nextR = row - 1;
                nextC = col - 1;
                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }

                nextR = 0;
                nextC = 0;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }


            } //Side cases
            else if (i == 0) {
                nextR = row - 1;
                nextC = j;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }

            } else if (i == row - 1) {
                nextR = 0;
                nextC = j;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }

            } else if (j == 0) {
                nextR = i;
                nextC = col - 1;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }


            } else if (j == col - 1) {
                nextR = i;
                nextC = 0;

                if (isValid(nextR, nextC, toFind, nextIndex, visited, puzzle)) {
                    return findUtil(toFind, puzzle, nextR, nextC, visited, sb, nextIndex,new ArrayList<>(list));

                }


            }


        }

        //mark last visited node(while backtracking) as false again so that it can be used again
        visited[i][j] = false;
        sb.deleteCharAt(sb.length()-1);


        return false;


    }


    private static boolean isValid(int i, int j, String toFind, int index, boolean[][] visited, Character[][] puzzle) {
        return (i >= 0 && j >= 0 && i < row && j < col && !visited[i][j] && puzzle[i][j] == toFind.charAt(index));
    }


    public static void main(String[] args) {

        Character[][] puzzle = new Character[][]{{'a', 'e', 'r', 'o', 'p', 's'},
                                                 {'b', 'h', 'a', 'l', 'l', 's'},
                                                 {'w', 'r', 'i', 's', 'l', 'o'},
                                                 {'a', 's', 'n', 'k', 't', 'q'}};

        String toFind = "slow";

        System.out.println(StringPuzzle.find(toFind,puzzle));

    }

}

- poorvank August 15, 2016 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

We can maintain a hashmap of char to position.
total of 26 keys.

eg:
r->(0,2),(1,3).

and for each position of the starting letter, we can do 8 searches in 8 directions.

comments/suggestions welcome.

Thanks,
Rohith Menon.

- Rohith Menon November 21, 2008 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

why do you want to maintain a hashmap? to create a hashmap u hv to travel all the positions.....and if you are travelling then at the same time you can check for the existance of the given word at that position???

- varun July 03, 2012 | 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