0% found this document useful (0 votes)
124 views24 pages

BackTracking Article GFG

Backtracking is an algorithmic technique used to solve problems by incrementally building solutions and removing those that fail to meet constraints. It can be applied to various problem types, including decision, optimization, and enumeration problems, with examples such as solving Sudoku, navigating a rat through a maze, and placing queens on a chessboard. The document details the approach, algorithms, and implementations for these examples, highlighting time and space complexities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
124 views24 pages

BackTracking Article GFG

Backtracking is an algorithmic technique used to solve problems by incrementally building solutions and removing those that fail to meet constraints. It can be applied to various problem types, including decision, optimization, and enumeration problems, with examples such as solving Sudoku, navigating a rat through a maze, and placing queens on a chessboard. The document details the approach, algorithms, and implementations for these examples, highlighting time and space complexities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

BackTracking Article GFG

Concept of Backtracking

Backtracking can be defined as a general algorithmic technique that considers searching


every possible combination in order to solve a computational problem.

What is Backtracking Algorithm?


Backtracking is an algorithmic technique for solving problems recursively by trying to build a
solution incrementally, one piece at a time, removing those solutions that fail to satisfy the
constraints of the problem at any point of time (by time, here, is referred to the time elapsed
till reaching any level of the search tree).

Types of Backtracking Algorithm


There are three types of problems in backtracking –

1. Decision Problem – In this, we search for a feasible solution.


2. Optimization Problem – In this, we search for the best solution.
3. Enumeration Problem – In this, we find all feasible solutions.

When can be Backtracking Algorithm used?


For example, consider the SudoKu solving Problem, we try filling digits one by one. Whenever
we find that current digit cannot lead to a solution, we remove it (backtrack) and try next
digit. This is better than naive approach (generating all possible combinations of digits and
then trying every combination one by one) as it drops a set of permutations whenever it
backtracks.

Rat in a Maze

Let us discuss Rat in a Maze as another example problem that can be solved using
Backtracking.

A Maze is given as N*N binary matrix of blocks where source block is the upper left most
block i.e., maze[0][0] and destination block is lower rightmost block i.e., maze[N-1][N-1]. A rat
starts from source and has to reach the destination. The rat can move only in two directions:
forward and down.

In the maze matrix, 0 means the block is a dead end and 1 means the block can be used in the
path from source to destination. Note that this is a simple version of the typical Maze
problem. For example, a more complex version can be that the rat can move in 4 directions
and a more complex version can be with a limited number of moves.

Following is an example maze.

Gray blocks are dead ends (value = 0).

Following is a binary matrix representation of the above maze.

{1, 0, 0, 0}
{1, 1, 0, 1}
{0, 1, 0, 0}
{1, 1, 1, 1}

Following is a maze with highlighted solution path.

Following is the solution matrix (output of program) for the above input matrix.

{1, 0, 0, 0}
{1, 1, 0, 0}
{0, 1, 0, 0}
{0, 1, 1, 1}
All entries in solution path are marked as 1.

Backtracking Algorithm: Backtracking is an algorithmic-technique for solving problems


recursively by trying to build a solution incrementally. Solving one piece at a time, and
removing those solutions that fail to satisfy the constraints of the problem at any point of
time (by time, here, is referred to the time elapsed till reaching any level of the search tree) is
the process of backtracking.

Approach: Form a recursive function, which will follow a path and check if the path reaches
the destination or not. If the path does not reach the destination then backtrack and try
other paths.

Algorithm:

1. Create a solution matrix, initially filled with 0’s.


2. Create a recursive function, which takes initial matrix, output matrix and position of rat (i,
j).
3. if the position is out of the matrix or the position is not valid then return.
4. Mark the position output[i][j] as 1 and check if the current position is destination or not. If
destination is reached print the output matrix and return.
5. Recursively call for position (i+1, j) and (i, j+1).
6. Unmark position (i, j), i.e output[i][j] = 0.
C++Java

import java.util.*;

import java.io.*;

import java.lang.*;

class Gfg

static int N;

static void printSolution(int sol[][])

for (int i = 0; i < N; i++) {

for (int j = 0; j < N; j++)

System.out.print( " " + sol[i][j] + " ");

System.out.println();

static boolean isSafe( int maze[][], int i, int j)

return (i < N && j < N && maze[i][j] == 1);

static boolean solveMaze(int maze[][])

int sol[][] = new int[N][N];


if (solveMazeRec(maze, 0, 0, sol) == false) {

System.out.print("Solution doesn't exist");

return false;

printSolution(sol);

return true;

static boolean solveMazeRec(int maze[][], int i, int j, int sol[][])

if (i == N - 1 && j == N - 1 && maze[i][j] == 1) {

sol[i][j] = 1;

return true;

if (isSafe(maze, i, j) == true) {

sol[i][j] = 1;

if (solveMazeRec(maze, i + 1, j, sol))

return true;

if (solveMazeRec(maze, i, j + 1, sol))

return true;

sol[i][j] = 0;
}

return false;

public static void main(String args[])

int maze[][] = { { 1, 0, 0, 0 },

{ 1, 1, 0, 1 },

{ 0, 1, 0, 0 },

{ 1, 1, 1, 1 } };

N = maze.length;

solveMaze(maze);

Output:

The 1 values show the path for rat

1 0 0 0
1 1 0 0
0 1 0 0
0 1 1 1

Complexity Analysis:

Time Complexity: O(2^(n^2)).


The recursion can run upper-bound 2^(n^2) times.
Space Complexity: O(n^2).
Output matrix is required so an extra space of size n*n is needed.

N-Queen Problem
Let us discuss N Queen as another example problem that can be solved using backtracking.
The N Queen is the problem of placing N chess queens on an N×N chessboard so that no two
queens attack each other. For example, the following is a solution for the 4 Queen problem.

The expected output is a binary matrix that has 1s for the blocks where queens are placed.
For example, the following is the output matrix for the above 4 queen solution.

{ 0, 1, 0, 0}
{ 0, 0, 0, 1}
{ 1, 0, 0, 0}
{ 0, 0, 1, 0}

Naive Algorithm
Generate all possible configurations of queens on board and print a configuration that
satisfies the given constraints.

while there are untried configurations

generate the next configuration

if queens don't attack in this configuration then

print this configuration;

Backtracking Algorithm
The idea is to place queens one by one in different columns, starting from the leftmost
column. When we place a queen in a column, we check for clashes with already placed
queens. In the current column, if we find a row for which there is no clash, we mark this row
and column as part of the solution. If we do not find such a row due to clashes, then we
backtrack and return false.

1) Start in the leftmost column

2) If all queens are placed

return true

3) Try all rows in the current column.

Do following for every tried row.


a) If the queen can be placed safely in this row

then mark this [row, column] as part of the

solution and recursively check if placing

queen here leads to a solution.

b) If placing the queen in [row, column] leads to

a solution then return true.

c) If placing queen doesn't lead to a solution then

unmark this [row, column] (Backtrack) and go to

step (a) to try other rows.

4) If all rows have been tried and nothing worked,

return false to trigger backtracking.

Implementation of Backtracking solution

C++Java

import java.util.*;

import java.io.*;

import java.lang.*;

class Gfg

static final int N = 4;

static int board[][] = { { 0, 0, 0, 0 },

{ 0, 0, 0, 0 },

{ 0, 0, 0, 0 },

{ 0, 0, 0, 0 } };

static void printSolution(int board[][])


{

for (int i = 0; i < N; i++) {

for (int j = 0; j < N; j++)

System.out.print(" " + board[i][j]

+ " ");

System.out.println();

static boolean isSafe(int row, int col)

int i, j;

for (i = 0; i < col; i++)

if (board[row][i] == 1)

return false;

for (i = row, j = col; i >= 0 && j >= 0; i--, j--)

if (board[i][j] == 1)

return false;

for (i = row, j = col; j >= 0 && i < N; i++, j--)

if (board[i][j] == 1)

return false;

return true;

}
static boolean solveRec(int col)

if (col == N)

return true;

for (int i = 0; i < N; i++) {

if (isSafe(i, col)) {

board[i][col] = 1;

if (solveRec(col + 1) == true)

return true;

board[i][col] = 0;

return false;

static boolean solve()

if (solveRec(0) == false) {

System.out.print("Solution does not exist");

return false;

}
printSolution(board);

return true;

public static void main(String args[])

solve();

Output:

0 0 1 0

1 0 0 0

0 0 0 1

0 1 0 0

Time Complexity: O(N!)


Auxiliary Space: O(N2)

Sudoku Problem

Given a partially filled 9x9 2D array 'grid[9][9]', the goal is to assign digits (from 1 to 9) to the
empty cells so that every row, column, and subgrid of size 3x3 contains exactly one instance
of the digits from 1 to 9.

Example:

Input:
grid = { {3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0} }
Output:
316578492
529134768
487629531
263415987
974863125
851792643
138947256
692351874
745286319
Explanation: Each row, column and 3*3 box of
the output matrix contains unique numbers.

Input:
grid = { { 3, 1, 6, 5, 7, 8, 4, 9, 2 },
{ 5, 2, 9, 1, 3, 4, 7, 6, 8 },
{ 4, 8, 7, 6, 2, 9, 5, 3, 1 },
{ 2, 6, 3, 0, 1, 5, 9, 8, 7 },
{ 9, 7, 4, 8, 6, 0, 1, 2, 5 },
{ 8, 5, 1, 7, 9, 2, 6, 4, 3 },
{ 1, 3, 8, 0, 4, 7, 2, 0, 6 },
{ 6, 9, 2, 3, 5, 1, 8, 7, 4 },
{ 7, 4, 5, 0, 8, 6, 3, 1, 0 } };
Output:
316578492
529134768
487629531
263415987
974863125
851792643
138947256
692351874
745286319
Explanation: Each row, column and 3*3 box of
the output matrix contains unique numbers.

Method 1: Simple.

Approach: The naive approach is to generate all possible configurations of numbers from 1 to
9 to fill the empty cells. Try every configuration one by one until the correct configuration is
found, i.e. for every unassigned position fill the position with a number from 1 to 9. After
filling all the unassigned position check if the matrix is safe or not. If safe print else recurs for
other cases.

Algorithm:

1. Create a function that checks if the given matrix is valid sudoku or not. Keep Hashmap for
the row, column and boxes. If any number has a frequency greater than 1 in the hashMap
return false else return true;
2. Create a recursive function that takes a grid and the current row and column index.
3. Check some base cases. If the index is at the end of the matrix, i.e. i=N-1 and j=N then
check if the grid is safe or not, if safe print the grid and return true else return false. The
other base case is when the value of column is N, i.e j = N, then move to next row, i.e. i++
and j = 0.
4. if the current index is not assigned then fill the element from 1 to 9 and recur for all 9
cases with the index of next element, i.e. i, j+1. if the recursive call returns true then break
the loop and return true.
5. if the current index is assigned then call the recursive function with index of next
element, i.e. i, j+1

Implementation:

C++Java

// Java program for above approach

public class Sudoku {

// N is the size of the 2D matrix N*N

static int N = 9;

/* Takes a partially filled-in grid and attempts

to assign values to all unassigned locations in

such a way to meet the requirements for

Sudoku solution (non-duplication across rows,

columns, and boxes) */

static boolean solveSudoku(int grid[][], int row,

int col)

{
/*if we have reached the 8th

row and 9th column (0

indexed matrix) ,

we are returning true to avoid further

backtracking */

if (row == N - 1 && col == N)

return true;

// Check if column value becomes 9 ,

// we move to next row

// and column start from 0

if (col == N) {

row++;

col = 0;

// Check if the current position

// of the grid already

// contains value >0, we iterate

// for next column

if (grid[row][col] != 0)

return solveSudoku(grid, row, col + 1);

for (int num = 1; num < 10; num++) {

// Check if it is safe to place


// the num (1-9) in the

// given row ,col ->we move to next column

if (isSafe(grid, row, col, num)) {

/* assigning the num in the current

(row,col) position of the grid and

assuming our assigned num in the position

is correct */

grid[row][col] = num;

// Checking for next

// possibility with next column

if (solveSudoku(grid, row, col + 1))

return true;

/* removing the assigned num , since our

assumption was wrong , and we go for next

assumption with diff num value */

grid[row][col] = 0;

return false;

/* A utility function to print grid */

static void print(int[][] grid)

for (int i = 0; i < N; i++) {


for (int j = 0; j < N; j++)

System.out.print(grid[i][j] + " ");

System.out.println();

// Check whether it will be legal

// to assign num to the

// given row, col

static boolean isSafe(int[][] grid, int row, int col,

int num)

// Check if we find the same num

// in the similar row , we

// return false

for (int x = 0; x <= 8; x++)

if (grid[row][x] == num)

return false;

// Check if we find the same num

// in the similar column ,

// we return false

for (int x = 0; x <= 8; x++)

if (grid[x][col] == num)

return false;
// Check if we find the same num

// in the particular 3*3

// matrix, we return false

int startRow = row - row % 3, startCol

= col - col % 3;

for (int i = 0; i < 3; i++)

for (int j = 0; j < 3; j++)

if (grid[i + startRow][j + startCol] == num)

return false;

return true;

// Driver Code

public static void main(String[] args)

int grid[][] = { { 3, 0, 6, 5, 0, 8, 4, 0, 0 },

{ 5, 2, 0, 0, 0, 0, 0, 0, 0 },

{ 0, 8, 7, 0, 0, 0, 0, 3, 1 },

{ 0, 0, 3, 0, 1, 0, 0, 8, 0 },

{ 9, 0, 0, 8, 6, 3, 0, 0, 5 },

{ 0, 5, 0, 0, 9, 0, 6, 0, 0 },

{ 1, 3, 0, 0, 0, 0, 2, 5, 0 },

{ 0, 0, 0, 0, 0, 0, 0, 7, 4 },

{ 0, 0, 5, 2, 0, 6, 3, 0, 0 } };

if (solveSudoku(grid, 0, 0))
print(grid);

else

System.out.println("No Solution exists");

Output

316578492

529134768

487629531

263415987

974863125

851792643

138947256

692351874

745286319

Complexity Analysis:

Time complexity: O(9^(n*n)).


For every unassigned index, there are 9 possible options so the time complexity is
O(9^(n*n)).
Space Complexity: O(n*n).
To store the output array a matrix is needed.

Method 2: Backtracking.

Approach:
Like all other Backtracking problems, Sudoku can be solved by one by one assigning numbers
to empty cells. Before assigning a number, check whether it is safe to assign. Check that the
same number is not present in the current row, current column and current 3X3 subgrid. After
checking for safety, assign the number, and recursively check whether this assignment leads
to a solution or not. If the assignment doesn't lead to a solution, then try the next number for
the current empty cell. And if none of the number (1 to 9) leads to a solution, return false and
print no solution exists.
Algorithm:

1. Create a function that checks after assigning the current index the grid becomes unsafe
or not. Keep Hashmap for a row, column and boxes. If any number has a frequency
greater than 1 in the hashMap return false else return true; hashMap can be avoided by
using loops.
2. Create a recursive function that takes a grid.
3. Check for any unassigned location. If present then assign a number from 1 to 9, check if
assigning the number to current index makes the grid unsafe or not, if safe then
recursively call the function for all safe cases from 0 to 9. if any recursive call returns
true, end the loop and return true. If no recursive call returns true then return false.
4. If there is no unassigned location then return true.

Implementation:

C++Java

/* A Backtracking program in

Java to solve Sudoku problem */

class GFG {

public static boolean isSafe(int[][] board, int row,

int col, int num)

// Row has the unique (row-clash)

for (int d = 0; d < board.length; d++) {

// Check if the number we are trying to

// place is already present in

// that row, return false;

if (board[row][d] == num) {

return false;

}
// Column has the unique numbers (column-clash)

for (int r = 0; r < board.length; r++) {

// Check if the number

// we are trying to

// place is already present in

// that column, return false;

if (board[r][col] == num) {

return false;

// Corresponding square has

// unique number (box-clash)

int sqrt = (int)Math.sqrt(board.length);

int boxRowStart = row - row % sqrt;

int boxColStart = col - col % sqrt;

for (int r = boxRowStart; r < boxRowStart + sqrt;

r++) {

for (int d = boxColStart;

d < boxColStart + sqrt; d++) {

if (board[r][d] == num) {

return false;

}
// if there is no clash, it's safe

return true;

public static boolean solveSudoku(int[][] board, int n)

int row = -1;

int col = -1;

boolean isEmpty = true;

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

if (board[i][j] == 0) {

row = i;

col = j;

// We still have some remaining

// missing values in Sudoku

isEmpty = false;

break;

if (!isEmpty) {

break;

}
// No empty space left

if (isEmpty) {

return true;

// Else for each-row backtrack

for (int num = 1; num <= n; num++) {

if (isSafe(board, row, col, num)) {

board[row][col] = num;

if (solveSudoku(board, n)) {

// print(board, n);

return true;

else {

// replace it

board[row][col] = 0;

return false;

public static void print(int[][] board, int N)

// We got the answer, just print it

for (int r = 0; r < N; r++) {


for (int d = 0; d < N; d++) {

System.out.print(board[r][d]);

System.out.print(" ");

System.out.print("\n");

if ((r + 1) % (int)Math.sqrt(N) == 0) {

System.out.print("");

// Driver Code

public static void main(String args[])

int[][] board

= new int[][] { { 3, 0, 6, 5, 0, 8, 4, 0, 0 },

{ 5, 2, 0, 0, 0, 0, 0, 0, 0 },

{ 0, 8, 7, 0, 0, 0, 0, 3, 1 },

{ 0, 0, 3, 0, 1, 0, 0, 8, 0 },

{ 9, 0, 0, 8, 6, 3, 0, 0, 5 },

{ 0, 5, 0, 0, 9, 0, 6, 0, 0 },

{ 1, 3, 0, 0, 0, 0, 2, 5, 0 },

{ 0, 0, 0, 0, 0, 0, 0, 7, 4 },

{ 0, 0, 5, 2, 0, 6, 3, 0, 0 } };

int N = board.length;
if (solveSudoku(board, N)) {

// print solution

print(board, N);

else {

System.out.println("No solution");

// This code is contributed

// by MohanDas

Output

316578492

529134768

487629531

263415987

974863125

851792643

138947256

692351874

745286319

Complexity Analysis:

Time complexity: O(9^(n*n)).


For every unassigned index, there are 9 possible options so the time complexity is
O(9^(n*n)). The time complexity remains the same but there will be some early pruning so
the time taken will be much less than the naive algorithm but the upper bound time
complexity remains the same.
Space Complexity: O(n*n).
To store the output array a matrix is needed.

You might also like