Photo by Henry Hustava on Unsplash

Minimum Knight Moves — Daily Challenge May

Amit Singh Rathore
Nerd For Tech
Published in
3 min readMay 15, 2021

--

Today’s question is from Daily Leetcode Coding Challenge — May Edition. It is a medium-tagged question. Let us look into the problem statement.

1197. Minimum Knight Moves

In an infinite chessboard with coordinates from -infinity to +infinity, you have a knight at square [0, 0].

A knight has 8 possible moves it can make, as illustrated below. Each move is two squares in a cardinal direction, then one square in an orthogonal direction.

Return the minimum number of steps needed to move the knight to the square [x, y]. It is guaranteed the answer exists.

Example:

Input: x = 5, y = 5
Output: 4
Explanation: [0, 0] → [2, 1] → [4, 2] → [3, 4] → [5, 5]

Understand the problem:

A Knight’s movement can be summarised as below in terms of coordinate increments considering a current position as x, y:

1. (x-1, y+2) ==> (-1, +2)
2. (x+1, y+2) ==> (+1, +2)
3. (x+2, y+1) ==> (+2, +1)
4. (x+2, y-1) ==> (+2, -1)
5. (x+1, y-2) ==> (+1, -2)
6. (x-1, y-2) ==> (-1, -2)
7. (x-2, y-1) ==> (-2, -1)
8. (x-2, y+1) ==> (-2, +1)

As we see at a given coordinate the Knight can move to 8 different positions. From there it can move the next seven(1 will be the start position or position from where it came) places. The minimum number of steps can be found using BFS traversal.

Also since the initial position is at (0, 0) we can restrict the moves in the positive region or first quadrant. We can do so if we take the absolute value of the target coordinate. We can do so since we only need to find the minimum number of steps. Also, we keep track of visiting positions.

Code Implementation:

def minKnightMoves(x, y):
x , y = abs(x), abs(y)
possible_moves = [
(1, 2), (2, 1), (-1, 2),
(-2, 1), (-1, -2), (-2, -1),
(1, -2), (2, -1)
]

que = collections.deque([[0, 0, 0]])
visited = set()
visited.add((0, 0))
while que:
qx, qy, d = que.popleft()
if x == qx and y == qy:
return d
for dx, dy in possible_moves:
nx, ny = qx + dx, qy + dy
if (nx, ny) not in visited and nx >=-2 and ny>=-2:
visited.add((nx, ny))
que.append([nx, ny, d + 1])

Complexity Analysis:

  • Time complexity: O(max(x²,y²)). This is due to the fact that every place the Knight covers a radius of 2x or 2y. The number of cells inside this circle is the max of x² or y².
  • Constant space: O(max(x²,y²)) at any level we store all nodes that can be reached from the previous level.

Approach 2

From the directions, we can optimize and only move in the (-1, -2) or (-2, -1) direction. In other words, the destination is always in the first quadrant. The moment we reach (0, 2) or (2, 0) or (1, 1) the knight cannot move further to (0, 0) or might go into the negative axis. If we are in (0, 2) move the night to (2, 1) then from there it could move to (0, 0). This takes 2 moves. The same applies to (1, 1) and (2,0). Similarly for (0, 1), it will need 3 steps to come back to (0, 0)

def minKnightMoves(self, x: int, y: int) -> int:
known_point_moves = {(0, 0): 0, (1, 1): 2, (1, 0): 3, (0, 1): 3, (2, 0): 2, (0, 2): 2}
def dfs(x, y):
if (x, y) in known_point_moves:
return cache[(x, y)]
res = min(dfs(abs(x-1), abs(y-2)), dfs(abs(x-2), abs(y-1))) + 1
known_point_moves[(x, y)] = res
return res
return dfs(abs(x), abs(y))

--

--

Amit Singh Rathore
Nerd For Tech

Staff Data Engineer @ Visa — Writes about Cloud | Big Data | ML