Interview Question
Country: United States
Using a HashSet like you are to prevent revisiting Positions will not work since it will prevent certain valid paths. It will fail on inputs like:
1, 0, 0, 0, 0, 0, 0
0, 2, 0, 2, 0, 2, 0
0, 0, 0, 0, 0, 0, 0
0, 2, 0, 2, 0, 2, 0
0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0
when it should be able to go (0,0) -> (2, 2) -> (4, 0) -> (6, 2) -> (4, 4) -> (2, 2) -> (0, 4)
That's a good point and I forgot about that. Instead of setting variable p to each "landing cell", I should have set it to the "opponent cell" instead.
So for the first if(direction == 0) I should set have set:
p = new Position(r-1, c-1);
I will edit the code above accordingly. Thanks for catching and let me know if you spot any other error.
So, basically figure out how many jumps can be done with given a game of checkers moving a single piece (a 'king'). This is roughly O(n^2) where n is the dimension of the board (8 in this case). More specifically, completing this via DFS using backtracking.
private static final int DIM = 6;
public static int getNumberOfJumps(int[][] board, Position start){
if(board == null){
throw new NullPointerException();
}
if(board.length < 3 || board.length >= DIM || board[0].length < 3 || board[0].length >= DIM){
throw new IllegalArgumentException();
}
if(start == null){
throw new NullPointerException();
}
if(start.x < 0 || start.x >= DIM || start.y < 0 || start.y >= DIM){
throw new IllegalArgumentException();
}
Worker worker = new Worker(board);
worker.search(start);
}
class Position{
int x;
int y;
Position(int x, int y){
this.x = x;
this.y = y;
}
}
class Worker{
private static final Position[] MOVE_DIRECTIONS = new Position[]{
new Position(-1,-1),
new Position(-1,1),
new Position(1,-1),
new Position(1,1)
};
int[][] board;
boolean[][] jumped;
Worker(int[][] board){
this.board = board;
this.jumped = new boolean[board.length][board[0].length];
}
private boolean isValidMove(Position opponent, Position end){
//destination within the board
if(end.x < 0 || end.x >= DIM || end.y < 0 || end.y >= DIM)
return false;
//destination is open
if(this.board[end.x][end.y] != 0)
return false;
//jumping over an opponent
if(this.board[opponent.x][opponent.y] != 2)
return false;
return true;
}
private Position[] genValidMoveData(Position start){
ArrayList<Position> working = new ArrayList<Position>();
for(Position direction : MOVE_DIRECTIONS){
Position opponent = new Position(start.x + direction.x, start.y + direction.y);
Position end = new Position(opponent.x+direction.x, opponent.y+direction.y);
if(isValidMove(opponent, end) && !jumped[opponent.x][opponent.y]){
working.add(opponent);
working.add(end);
}
}
return working.toArray();
}
int search(Position start){
int max = 0;
Position[] moves = genValidMoveData(start);
for(int i = 0; i < moves.length; i+=2){
Position opponent = moves[i];
Position dest = moves[i+1];
this.jumped[opponent.x][opponent.y] = true;
int val = search(dest)+1;
if(val > max){
max = val;
}
this.jumped[opponent.x][opponent.y] = false;
}
return max;
}
}
First add a "fence" around the original grid, so that the original grid is surrounded by 2 rows each on the top & bottom, and 2 cols each on the left & right. Then set the value for these fence positions to be -1. That way you can check the opponent cell and landing cell without worrying about array out of bounds. After that, just do DFS.
The following code is untested. It also seems quite long, which would be hard to implement during an actual interview.
- Sunny November 28, 2014