- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 76 lines of Java from the credited upstream file 353.java.
- The implementation visibly relies on sequence storage, hash lookup, ordered lookup, work queue.
- No explicit loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class SnakeGame {2 /**3 * Initialize your data structure here.4 *5 * @param width - screen width6 * @param height - screen height7 * @param food - A list of food positions E.g food = [[1,1], [1,0]] means the8 * first food is positioned at [1,1], the second is at [1,0].9 */10 public SnakeGame(int width, int height, int[][] food) {11 this.width = width;12 this.height = height;13 this.food = food;14 lookup.add(getId(0, 0));15 body.offerLast(getId(0, 0));16 }17 18 /**19 * Moves the snake.20 *21 * @param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down22 * @return The game's score after the move. Return -1 if game over. Game over23 * when snake crosses the screen boundary or bites its body.24 */25 public int move(String direction) {26 27 int i = body.peekFirst() / width;28 int j = body.peekFirst() % width;29 30 31 if (direction.equals("U") && --i < 0)32 return -1;33 if (direction.equals("L") && --j < 0)34 return -1;35 if (direction.equals("R") && ++j == width)36 return -1;37 if (direction.equals("D") && ++i == height)38 return -1;39 40 final int newHead = getId(i, j);41 42 43 if (k < food.length && i == food[k][0] && j == food[k][1]) {44 lookup.add(newHead);45 body.offerFirst(newHead);46 ++k;47 return ++score;48 }49 50 51 if (newHead != body.peekLast() && lookup.contains(newHead))52 return -1;53 54 55 56 57 lookup.remove(body.peekLast());58 lookup.add(newHead);59 body.pollLast();60 body.offerFirst(newHead);61 return score;62 }63 64 private int width;65 private int height;66 private int score = 0;67 private int k = 0; 68 private int[][] food;69 private Set<Integer> lookup = new HashSet<>();70 private Deque<Integer> body = new ArrayDeque<>(); 71 72 private int getId(int i, int j) {73 return i * width + j;74 }75}76