353. Design Snake Game
Given a non-empty array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
Input: [2,2,1]
Output: 1
Example 2:
Input: [4,1,2,1,2]
Output: 4
- Double ended queue
I tried to use a hashset to record the body of the snake, but it is much slower than a leaner search over the queue. why???
class SnakeGame {
ArrayDeque<Node> q = new ArrayDeque<>();
int p;
int score;
int[][] food;
int n, m;
/** Initialize your data structure here.
@param width - screen width
@param height - screen height
@param food - A list of food positions
E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0]. */
public SnakeGame(int w, int h, int[][] food) {
q.offer(new Node(0, 0));
this.food = food;
n = h;
m = w;
}
class Node {
int i;
int j;
public Node(int i, int j) {
this.i = i;
this.j = j;
}
}
/** Moves the snake.
@param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down
@return The game's score after the move. Return -1 if game over.
Game over when snake crosses the screen boundary or bites its body. */
public int move(String direction) {
Node curr = q.peekLast(), tail = q.peekFirst();
int ni = curr.i, nj = curr.j, ti = tail.i, tj = tail.j;
switch(direction) {
case "U" : ni--; break;
case "D" : ni++; break;
case "L" : nj--; break;
case "R" : nj++;
}
if(ni < 0 || nj < 0 || ni >= n || nj >= m) return -1;
if(p == food.length || !(ni == food[p][0] && nj == food[p][1])) { // not eat, give up the tail
q.pollFirst();
} else {
score++;
p++;
}
for(Node n : q) {
if(ni == n.i && nj == n.j) return -1;
}
Node nh = new Node(ni, nj);
q.offerLast(nh);
return p;
}
}
- MLE failed on a 10000 * 10000 matrix input.
class SnakeGame {
int[][] matrix;
int fp;
int score;
Node head, tail;
HashMap<String, int[]> map = new HashMap<>();
int[][] food;
/** Initialize your data structure here.
@param width - screen width
@param height - screen height
@param food - A list of food positions
E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0]. */
public SnakeGame(int width, int height, int[][] food) {
this.food = food;
matrix = new int[height][width];
if(food.length > 0) matrix[food[fp][0]][food[fp++][1]] = 2;
matrix[0][0] = 1;
head = new Node(0, 0);
tail = head;
map.put("U", new int[]{-1,0});
map.put("D", new int[]{1,0});
map.put("L", new int[]{0,-1});
map.put("R", new int[]{0,1});
}
class Node {
int i;
int j;
Node next;
public Node(int i, int j) {
this.i = i;
this.j = j;
}
}
/** Moves the snake.
@param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down
@return The game's score after the move. Return -1 if game over.
Game over when snake crosses the screen boundary or bites its body. */
public int move(String direction) {
int[] d = map.get(direction);
int i = head.i + d[0], j = head.j + d[1];
if(i < 0 || j < 0 || i >= matrix.length || j >= matrix[0].length) {
return -1;
}
if(matrix[i][j] == 1 && !(i == tail.i && j == tail.j)) return -1;
Node newHead = new Node(i, j);
head.next = newHead;
head = newHead;
if(matrix[i][j] != 2) {
matrix[tail.i][tail.j] = 0;
Node newTail = tail.next;
tail.next = null;
tail = newTail;
}
if(matrix[i][j] == 2) { // food
score++;
if(fp < food.length)
matrix[food[fp][0]][food[fp++][1]] = 2;
}
matrix[i][j] = 1;
return score;
}