Given a square chessboard of size n × n, the initial position knightPos[] and target position targetPos[] of a Knight are given. Find the minimum number of moves required for the Knight to reach targetPos.
A Knight moves in an L-shape, covering 2 cells in one direction and 1 cell perpendicular to it. From (x, y), it can move to:
(x ± 2, y ± 1)
(x ± 1, y ± 2)
This gives at most 8 possible moves:
Note: The positions are given using 1-based indexing.
Examples:
Input: n = 3, knightPos[] = [3, 3], targetPos[]= [1, 2] Output: 1 Explanation: Knight takes 1 step to reach from (3, 3) to (1 ,2).
Input: n = 6, knightPos[] = [1, 3], targetPos[] = [5, 1] Output: 2 Explanation: In above diagram Knight takes 2 step to reach from (1, 3) to (5, 1): (1, 3) -> (3, 2) -> (5, 1)
[Naive Approach] Recursion and Backtracking - Exponential Time and O(n^2) Auxiliary Space
The idea is to explore all possible paths that the Knight can take from the initial position to the target and find the path requiring the minimum number of steps.
From each position, the Knight can make at most 8 moves.
We recursively explore every valid move until the target is reached.
A visited array is used to avoid revisiting a cell in the current path.
After exploring a move, we unmark the cell to allow it in other paths.
C++
#include<bits/stdc++.h>usingnamespacestd;intsolve(intx,inty,inttx,intty,intn,vector<vector<bool>>&visited){// If target is reachedif(x==tx&&y==ty)return0;intans=INT_MAX;// All 8 possible Knight movesintdx[]={2,2,-2,-2,1,1,-1,-1};intdy[]={1,-1,1,-1,2,-2,2,-2};for(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;intsteps=solve(nx,ny,tx,ty,n,visited);if(steps!=INT_MAX)ans=min(ans,1+steps);// Backtrackvisited[nx][ny]=false;}}returnans;}intminStepToReachTarget(vector<int>&knightPos,vector<int>&targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;vector<vector<bool>>visited(n,vector<bool>(n,false));visited[x][y]=true;returnsolve(x,y,tx,ty,n,visited);}intmain(){intn=3;vector<int>knightPos={3,3};vector<int>targetPos={1,2};cout<<minStepToReachTarget(knightPos,targetPos,n);return0;}
Java
classGFG{staticintsolve(intx,inty,inttx,intty,intn,boolean[][]visited){// If target is reachedif(x==tx&&y==ty)return0;intans=Integer.MAX_VALUE;// All 8 possible Knight movesint[]dx={2,2,-2,-2,1,1,-1,-1};int[]dy={1,-1,1,-1,2,-2,2,-2};for(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;intsteps=solve(nx,ny,tx,ty,n,visited);if(steps!=Integer.MAX_VALUE)ans=Math.min(ans,1+steps);// Backtrackvisited[nx][ny]=false;}}returnans;}staticintminStepToReachTarget(int[]knightPos,int[]targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;boolean[][]visited=newboolean[n][n];visited[x][y]=true;returnsolve(x,y,tx,ty,n,visited);}publicstaticvoidmain(String[]args){intn=3;int[]knightPos={3,3};int[]targetPos={1,2};System.out.println(minStepToReachTarget(knightPos,targetPos,n));}}
Python
defsolve(x,y,tx,ty,n,visited):# If target is reachedifx==txandy==ty:return0ans=float('inf')# All 8 possible Knight movesdx=[2,2,-2,-2,1,1,-1,-1]dy=[1,-1,1,-1,2,-2,2,-2]foriinrange(8):nx=x+dx[i]ny=y+dy[i]# Check if the new position is valid and unvisitedif(nx>=0andnx<nandny>=0andny<nandnotvisited[nx][ny]):visited[nx][ny]=Truesteps=solve(nx,ny,tx,ty,n,visited)ifsteps!=float('inf'):ans=min(ans,1+steps)# Backtrackvisited[nx][ny]=FalsereturnansdefminStepToReachTarget(knightPos,targetPos,n):# Convert 1-based indexing to 0-based indexingx=knightPos[0]-1y=knightPos[1]-1tx=targetPos[0]-1ty=targetPos[1]-1visited=[[Falsefor_inrange(n)]for_inrange(n)]visited[x][y]=Truereturnsolve(x,y,tx,ty,n,visited)if__name__=="__main__":n=3knightPos=[3,3]targetPos=[1,2]print(minStepToReachTarget(knightPos,targetPos,n))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticintsolve(intx,inty,inttx,intty,intn,bool[,]visited){// If target is reachedif(x==tx&&y==ty)return0;intans=int.MaxValue;// All 8 possible Knight movesint[]dx={2,2,-2,-2,1,1,-1,-1};int[]dy={1,-1,1,-1,2,-2,2,-2};for(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx,ny]){visited[nx,ny]=true;intsteps=solve(nx,ny,tx,ty,n,visited);if(steps!=int.MaxValue)ans=Math.Min(ans,1+steps);// Backtrackvisited[nx,ny]=false;}}returnans;}staticintminStepToReachTarget(int[]knightPos,int[]targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;bool[,]visited=newbool[n,n];visited[x,y]=true;returnsolve(x,y,tx,ty,n,visited);}staticvoidMain(){intn=3;int[]knightPos={3,3};int[]targetPos={1,2};Console.WriteLine(minStepToReachTarget(knightPos,targetPos,n));}}
JavaScript
functionsolve(x,y,tx,ty,n,visited){// If target is reachedif(x===tx&&y===ty)return0;letans=Infinity;// All 8 possible Knight movesletdx=[2,2,-2,-2,1,1,-1,-1];letdy=[1,-1,1,-1,2,-2,2,-2];for(leti=0;i<8;i++){letnx=x+dx[i];letny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;letsteps=solve(nx,ny,tx,ty,n,visited);if(steps!==Infinity)ans=Math.min(ans,1+steps);// Backtrackvisited[nx][ny]=false;}}returnans;}functionminStepToReachTarget(knightPos,targetPos,n){// Convert 1-based indexing to 0-based indexingletx=knightPos[0]-1;lety=knightPos[1]-1;lettx=targetPos[0]-1;letty=targetPos[1]-1;letvisited=Array.from({length:n},()=>Array(n).fill(false));visited[x][y]=true;returnsolve(x,y,tx,ty,n,visited);}// Driver codeletn=3;letknightPos=[3,3];lettargetPos=[1,2];console.log(minStepToReachTarget(knightPos,targetPos,n));
Output
1
[Expected Approch] BFS - Shortest Path in O(n^2) Time and O(n^2) Space
The idea is to treat the chessboard as an unweighted graph and use Breadth-First Search (BFS) to find the shortest path from the Knight's initial position to the target position.
We can view the chessboard as a graph:
Each cell of the chessboard represents a node.
Each valid Knight move represents an edge between two cells.
The Knight's initial position is the starting node.
The target position is the destination node.
Every Knight move takes exactly 1 step, so all edges have the same cost.
Therefore, finding the minimum number of Knight moves is equivalent to finding the shortest path between two nodes in an unweighted graph.
BFS is well suited for this because it explores the graph level by level.
Steps:
Convert the starting and target positions from 1-based to 0-based indexing.
Add the starting position to the queue with 0 steps and mark it as visited.
Remove a position from the queue and check all 8 possible Knight moves.
For every valid and unvisited position, mark it as visited and add it to the queue with one more step.
If the target position is reached, return the number of steps.
If the target cannot be reached, return -1.
C++
#include<bits/stdc++.h>usingnamespacestd;intminStepToReachTarget(vector<int>&knightPos,vector<int>&targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;// All 8 possible Knight movesintdx[]={2,2,-2,-2,1,1,-1,-1};intdy[]={1,-1,1,-1,2,-2,2,-2};// Queue stores position and number of stepsqueue<pair<pair<int,int>,int>>q;// Mark visited cellsvector<vector<bool>>visited(n,vector<bool>(n,false));// Start BFS from the initial positionq.push({{x,y},0});visited[x][y]=true;while(!q.empty()){intx=q.front().first.first;inty=q.front().first.second;intsteps=q.front().second;q.pop();// If target is reachedif(x==tx&&y==ty)returnsteps;// Try all 8 possible Knight movesfor(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;// Add the new position with updated stepsq.push({{nx,ny},steps+1});}}}return-1;}intmain(){intn=6;vector<int>knightPos={4,5};vector<int>targetPos={1,1};cout<<minStepToReachTarget(knightPos,targetPos,n);return0;}
Java
importjava.util.Queue;importjava.util.LinkedList;classGFG{staticintminStepToReachTarget(int[]knightPos,int[]targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;// All 8 possible Knight movesint[]dx={2,2,-2,-2,1,1,-1,-1};int[]dy={1,-1,1,-1,2,-2,2,-2};// Queue stores position and number of stepsQueue<int[]>q=newLinkedList<>();// Mark visited cellsboolean[][]visited=newboolean[n][n];// Start BFS from the initial positionq.offer(newint[]{x,y,0});visited[x][y]=true;while(!q.isEmpty()){int[]curr=q.poll();x=curr[0];y=curr[1];intsteps=curr[2];// If target is reachedif(x==tx&&y==ty)returnsteps;// Try all 8 possible Knight movesfor(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;// Add the new position with updated stepsq.offer(newint[]{nx,ny,steps+1});}}}return-1;}publicstaticvoidmain(String[]args){intn=6;int[]knightPos={4,5};int[]targetPos={1,1};System.out.println(minStepToReachTarget(knightPos,targetPos,n));}}
Python
fromcollectionsimportdequedefminStepToReachTarget(knightPos,targetPos,n):# Convert 1-based indexing to 0-based indexingx=knightPos[0]-1y=knightPos[1]-1tx=targetPos[0]-1ty=targetPos[1]-1# All 8 possible Knight movesdx=[2,2,-2,-2,1,1,-1,-1]dy=[1,-1,1,-1,2,-2,2,-2]# Queue stores position and number of stepsq=deque()# Mark visited cellsvisited=[[False]*nfor_inrange(n)]# Start BFS from the initial positionq.append((x,y,0))visited[x][y]=Truewhileq:x,y,steps=q.popleft()# If target is reachedifx==txandy==ty:returnsteps# Try all 8 possible Knight movesforiinrange(8):nx=x+dx[i]ny=y+dy[i]# Check if the new position is valid and unvisitedif(nx>=0andnx<nandny>=0andny<nandnotvisited[nx][ny]):visited[nx][ny]=True# Add the new position with updated stepsq.append((nx,ny,steps+1))return-1if__name__=="__main__":n=6knightPos=[4,5]targetPos=[1,1]print(minStepToReachTarget(knightPos,targetPos,n))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticintminStepToReachTarget(int[]knightPos,int[]targetPos,intn){// Convert 1-based indexing to 0-based indexingintx=knightPos[0]-1;inty=knightPos[1]-1;inttx=targetPos[0]-1;intty=targetPos[1]-1;// All 8 possible Knight movesint[]dx={2,2,-2,-2,1,1,-1,-1};int[]dy={1,-1,1,-1,2,-2,2,-2};// Queue stores position and number of stepsQueue<int[]>q=newQueue<int[]>();// Mark visited cellsbool[,]visited=newbool[n,n];// Start BFS from the initial positionq.Enqueue(newint[]{x,y,0});visited[x,y]=true;while(q.Count>0){int[]curr=q.Dequeue();x=curr[0];y=curr[1];intsteps=curr[2];// If target is reachedif(x==tx&&y==ty)returnsteps;// Try all 8 possible Knight movesfor(inti=0;i<8;i++){intnx=x+dx[i];intny=y+dy[i];// Check if the new position is valid and unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx,ny]){visited[nx,ny]=true;// Add the new position with updated stepsq.Enqueue(newint[]{nx,ny,steps+1});}}}return-1;}staticvoidMain(){intn=6;int[]knightPos={4,5};int[]targetPos={1,1};Console.WriteLine(minStepToReachTarget(knightPos,targetPos,n));}}
JavaScript
functionminStepToReachTarget(knightPos,targetPos,n){// Convert 1-based indexing to 0-based indexingletx=knightPos[0]-1;lety=knightPos[1]-1;lettx=targetPos[0]-1;letty=targetPos[1]-1;// All 8 possible Knight movesletdx=[2,2,-2,-2,1,1,-1,-1];letdy=[1,-1,1,-1,2,-2,2,-2];// Queue stores position and number of stepsletq=[];// Mark visited cellsletvisited=Array.from({length:n},()=>Array(n).fill(false));// Start BFS from the initial positionq.push([x,y,0]);visited[x][y]=true;letfront=0;while(front<q.length){letcurr=q[front++];x=curr[0];y=curr[1];letsteps=curr[2];// If target is reachedif(x===tx&&y===ty)returnsteps;// Try all 8 possible Knight movesfor(leti=0;i<8;i++){letnx=x+dx[i];letny=y+dy[i];// Check if the new position is valid and// unvisitedif(nx>=0&&nx<n&&ny>=0&&ny<n&&!visited[nx][ny]){visited[nx][ny]=true;// Add the new position with updated stepsq.push([nx,ny,steps+1]);}}}return-1;}// Driver codeletn=6;letknightPos=[4,5];lettargetPos=[1,1];console.log(minStepToReachTarget(knightPos,targetPos,n));