Skip to content

Latest commit

 

History

History
136 lines (106 loc) · 4.36 KB

1197.Minimum_Knight_Moves.md

File metadata and controls

136 lines (106 loc) · 4.36 KB
  1. Minimum Knight Moves

中等 https://leetcode-cn.com/problems/minimum-knight-moves/

In an infinite chess board 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 1:

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

Example 2:

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

Constraints:

-300 <= x, y <= 300
0 <= |x| + |y| <= 300

相关企业

  • 谷歌 Google|5
  • Facebook|5
  • 亚马逊 Amazon|3
  • 微软 Microsoft|2

相关标签

  • Breadth-First Search

隐藏提示1

  • You can simulate the movements since the limits are low.

隐藏提示2

  • Is there a search algorithm applicable to this problem?

隐藏提示3

  • Since we want the minimum number of moves, we can use Breadth First Search.

BFS + pruning

class Solution:
    def minKnightMoves(self, x: int, y: int) -> int:
        if x == 0 and y == 0:
            return 0

        stepcount = 0
        myqueue_route_record = deque([[0, 0]]) # class collections.deque([iterable])
        visitedsquares = set()
        visitedsquares.add((0, 0)) # == set([(0,0)])

        while myqueue_route_record:
            stepcount += 1
            currlevelLength = len(myqueue_route_record)
            for _ in range(currlevelLength):
                currcell = myqueue_route_record.popleft()
                if self._checkEightDirections(currcell[0], currcell[1], myqueue_route_record, visitedsquares, x, y):
                    return stepcount 
            
    def _checkEightDirections(self, curr_x, curr_y, myqueue_route_record, visitedsquares, target_x, target_y):
        offsets = [[1, 2], [1, -2], [-1, 2], [-1, -2], [2, 1], [2, -1], [-2, 1], [-2, -1]]
        for offset in offsets:
            new_x = curr_x + offset[0]
            new_y = curr_y + offset[1]
            if new_x == target_x and new_y == target_y:
                return True
            elif (new_x, new_y) in visitedsquares:
                continue
            else:
                myqueue_route_record.append([new_x, new_y])
                visitedsquares.add((new_x, new_y))

bi-BFS

class Solution:
    def minKnightMoves(self, x: int, y: int) -> int:
        if x == 0 and y == 0:
            return 0

        stepcounter = 0
        forwardqueue_route_record = collections.deque([[0,0]])
        forward_visitedcells = set([(0,0)])
        backwardqueue_route_record = collections.deque([[x,y]])
        backward_visitedcells = set([(x,y)])

        while forwardqueue_route_record and backwardqueue_route_record:
            stepcounter += 1
            curr_level_length = len(forwardqueue_route_record)
            for _ in range(curr_level_length):
                currcell = forwardqueue_route_record.popleft()
                if self.if8DirectionsContainTarget(currcell, forwardqueue_route_record, forward_visitedcells, backward_visitedcells, x, y):
                    return stepcounter 

            stepcounter += 1
            curr_level_length = len(backwardqueue_route_record)
            for _ in range(curr_level_length):
                currcell = backwardqueue_route_record.popleft()
                if self.if8DirectionsContainTarget(currcell, backwardqueue_route_record, backward_visitedcells, forward_visitedcells, x, y):
                    return stepcounter 
            
        return stepcounter
    
    def if8DirectionsContainTarget(self, currcell, myqueue_route_record, visitedcells, opposite_visitedcells, targetx, targety):
        offsets = [[1,2], [1,-2], [-1,2], [-1,-2], [2,1], [2,-1], [-2,-1], [-2,1]]
        currx = currcell[0]
        curry = currcell[1]
        for offset in offsets:
            newx = currx + offset[0]
            newy = curry + offset[1]
            if (newx, newy) in opposite_visitedcells:# this diff than BFS version
                return True
            elif (newx, newy) in visitedcells:
                continue
            else:
                myqueue_route_record.append([newx, newy])
                visitedcells.add((newx, newy))
        return False