Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Practice Divide and Conquer
  • MCQs on Divide and Conquer
  • Tutorial on Divide & Conquer
  • Binary Search
  • Merge Sort
  • Quick Sort
  • Calculate Power
  • Strassen's Matrix Multiplication
  • Karatsuba Algorithm
  • Divide and Conquer Optimization
  • Closest Pair of Points
Open In App
Next Article:
Count Inversions of an Array
Next article icon

Tiling Problem – L Shaped

Last Updated : 07 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an n×n board (where n = 2k and k≥1), with one missing cell, the task is to fill the remaining cells using L-shaped tiles. An L-shaped tile covers 3 cells in a 2×2 grid, with one cell missing. You need to tile the entire board using the L-shaped tiles, ensuring that the missing cell remains uncovered.

ex1

Note: There can be multiple valid ways to tile the board based on the position of the missing cell and the order in which tiles are placed. Your solution may output any one of these valid tilings.

Examples: 

Input: n = 2, missing_cell = (0,0)
Output: [[-1,1], [1, 1]]

2

Explanation: Coordinate (0, 0) is marked. So, no tile is there. In the remaining three positions, a tile is placed with its number as 1.

Input : n = 4, missing_cell = (0,1)
Output: [[3, -1, 2, 2], [3, 3, 1, 2], [4, 1, 1, 5], [4, 4, 5, 5]]

1

Explanation: In this 4×4 grid, the cell at position (0,1) is missing, and the rest using L-shaped tromino tiles, each marked with a unique number, ensuring all other cells are covered without overlapping.

Table of Content

  • [Naive Approach] Using Recursion and Backtracking
  • [Expected Approach] Using Divide and Conquer algorithm

[Naive Approach] Using Recursion and Backtracking

We will exploring all possible ways to place L-shaped tiles on the grid and leaving exactly one predefined missing cell. It begins by scanning the board to find the first empty cell. For that cell, it attempts to place each of the four possible L-shaped tromino configurations. If a placement is valid, it places the tile and recursively proceeds to fill the rest of the board. If a dead-end is reached, the algorithm backtracks by removing the last placed tile and trying the next configuration. This process continues until the board is fully tiled or all possibilities are exhausted.

C++
#include <iostream> #include <vector> using namespace std;  // Define the four L-shaped configurations const vector<vector<pair<int, int>>> TROMINO_SHAPES = {     {{0, 0}, {0, 1}, {1, 0}},  // ┌     {{0, 0}, {0, 1}, {1, 1}},  // ┐     {{0, 0}, {1, 0}, {1, 1}},  // └     {{0, 0}, {1, 0}, {1, -1}}  // ┘ };  bool isValid(vector<vector<int>>& board, int r, int c,              const vector<pair<int, int>>& shape, int size) {     for (const auto& offset : shape) {         int nr = r + offset.first;         int nc = c + offset.second;         if (nr < 0 || nr >= size || nc < 0 || nc >= size || board[nr][nc] != 0)             return false;     }     return true; }  void place(vector<vector<int>>& board, int r, int c,            const vector<pair<int, int>>& shape, int tileId) {     for (const auto& offset : shape) {         board[r + offset.first][c + offset.second] = tileId;     } }  void removeL(vector<vector<int>>& board, int r, int c,              const vector<pair<int, int>>& shape) {     for (const auto& offset : shape) {         board[r + offset.first][c + offset.second] = 0;     } }  bool findNext0(vector<vector<int>>& board, int size,                int& outR, int& outC) {     for (int r = 0; r < size; ++r) {         for (int c = 0; c < size; ++c) {             if (board[r][c] == 0) {                 outR = r;                 outC = c;                 return true;             }         }     }     return false; }  // Main recursive function to fill bool tileBoard(vector<vector<int>>& board, int size, int tileId) {     int r, c;     if (!findNext0(board, size, r, c)) {         return true;  // All cells filled successfully     }      for (const auto& shape : TROMINO_SHAPES) {         if (isValid(board, r, c, shape, size)) {             place(board, r, c, shape, tileId);             if (tileBoard(board, size, tileId + 1)) {                 return true;  // Found valid solution             }             removeL(board, r, c, shape);         }     }      return false;  // No valid placement, backtrack }  vector<vector<int>> tiling(int n, pair<int, int> missing) {     vector<vector<int>> board(n, vector<int>(n, 0));     board[missing.first][missing.second] = -1;      if (tileBoard(board, n, 1))         return board;      return {{-1}}; }  int main() {     int n = 4;  // Must be 2^k     pair<int, int> missing = {0, 1};      vector<vector<int>> grid = tiling(n, missing);      for (const auto& row : grid) {         for (int cell : row) {             cout << cell << " ";         }         cout << "\n";     }      return 0; } 
Java
// Import necessary packages import java.util.*;  public class TrominoTiling {          // Define the four L-shaped configurations     private static final int[][][] TROMINO_SHAPES = {         {{0, 0}, {0, 1}, {1, 0}},  // ┌         {{0, 0}, {0, 1}, {1, 1}},  // ┐         {{0, 0}, {1, 0}, {1, 1}},  // └         {{0, 0}, {1, 0}, {1, -1}}  // ┘     };      private static boolean isValid(int[][] board, int r, int c, int[][] shape, int size) {         for (int[] offset : shape) {             int nr = r + offset[0];             int nc = c + offset[1];             if (nr < 0 || nr >= size || nc < 0 || nc >= size || board[nr][nc] != 0)                 return false;         }         return true;     }      private static void place(int[][] board, int r, int c, int[][] shape, int tileId) {         for (int[] offset : shape) {             board[r + offset[0]][c + offset[1]] = tileId;         }     }      private static void removeL(int[][] board, int r, int c, int[][] shape) {         for (int[] offset : shape) {             board[r + offset[0]][c + offset[1]] = 0;         }     }      private static boolean findNext0(int[][] board, int size, int[] out) {         for (int r = 0; r < size; ++r) {             for (int c = 0; c < size; ++c) {                 if (board[r][c] == 0) {                     out[0] = r;                     out[1] = c;                     return true;                 }             }         }         return false;     }      // Main recursive function to fill     private static boolean tileBoard(int[][] board, int size, int tileId) {         int[] pos = new int[2];         if (!findNext0(board, size, pos)) {             return true;  // All cells filled successfully         }          int r = pos[0];         int c = pos[1];          for (int[][] shape : TROMINO_SHAPES) {             if (isValid(board, r, c, shape, size)) {                 place(board, r, c, shape, tileId);                 if (tileBoard(board, size, tileId + 1)) {                     return true;  // Found valid solution                 }                 removeL(board, r, c, shape);             }         }          return false;  // No valid placement, backtrack     }      public static int[][] tiling(int n, int[] missing) {         int[][] board = new int[n][n];         board[missing[0]][missing[1]] = -1;          if (tileBoard(board, n, 1))             return board;          return new int[][]{{-1}};     }      public static void main(String[] args) {         int n = 4;  // Must be 2^k         int[] missing = {0, 1};          int[][] grid = tiling(n, missing);          for (int[] row : grid) {             for (int cell : row) {                 System.out.print(cell + " ");             }             System.out.println();         }     } } 
Python
# Define the four L-shaped configurations TROMINO_SHAPES = [     [(0, 0), (0, 1), (1, 0)],  # ┌     [(0, 0), (0, 1), (1, 1)],  # ┐     [(0, 0), (1, 0), (1, 1)],  # └     [(0, 0), (1, 0), (1, -1)]  # ┘ ]  def is_valid(board, r, c, shape, size):     for offset in shape:         nr = r + offset[0]         nc = c + offset[1]         if nr < 0 or nr >= size or nc < 0 or nc >= size or board[nr][nc] != 0:             return False     return True  def place(board, r, c, shape, tile_id):     for offset in shape:         board[r + offset[0]][c + offset[1]] = tile_id  def remove_l(board, r, c, shape):     for offset in shape:         board[r + offset[0]][c + offset[1]] = 0   def find_next_0(board, size):     for r in range(size):         for c in range(size):             if board[r][c] == 0:                 return r, c     return None, None  # Main recursive function to fill  def tile_board(board, size, tile_id):     r, c = find_next_0(board, size)     if r is None:         return True  # All cells filled successfully      for shape in TROMINO_SHAPES:         if is_valid(board, r, c, shape, size):             place(board, r, c, shape, tile_id)             if tile_board(board, size, tile_id + 1):                 return True  # Found valid solution             remove_l(board, r, c, shape)      return False  # No valid placement, backtrack   def tiling(n, missing):     board = [[0] * n for _ in range(n)]     board[missing[0]][missing[1]] = -1      if tile_board(board, n, 1):         return board      return [[-1]]  if __name__ == '__main__':     n = 4  # Must be 2^k     missing = (0, 1)      grid = tiling(n, missing)      for row in grid:         print(' '.join(map(str, row))) 
C#
using System;  public class TrominoTiling {     // Define the four L-shaped configurations     private static readonly int[][][] TROMINO_SHAPES = new int[][][]     {         new int[][] { new int[] {0, 0}, new int[] {0, 1}, new int[] {1, 0} }, // ┌         new int[][] { new int[] {0, 0}, new int[] {0, 1}, new int[] {1, 1} }, // ┐         new int[][] { new int[] {0, 0}, new int[] {1, 0}, new int[] {1, 1} }, // └         new int[][] { new int[] {0, 0}, new int[] {1, 0}, new int[] {1, -1} } // ┘     };      private static bool IsValid(int[,] board, int r, int c, int[][] shape, int size)     {         foreach (var offset in shape)         {             int nr = r + offset[0];             int nc = c + offset[1];             if (nr < 0 || nr >= size || nc < 0 || nc >= size || board[nr, nc] != 0)                 return false;         }         return true;     }      private static void Place(int[,] board, int r, int c, int[][] shape, int tileId)     {         foreach (var offset in shape)         {             board[r + offset[0], c + offset[1]] = tileId;         }     }      private static void RemoveL(int[,] board, int r, int c, int[][] shape)     {         foreach (var offset in shape)         {             board[r + offset[0], c + offset[1]] = 0;         }     }      private static bool FindNext0(int[,] board, int size, out int r, out int c)     {         for (r = 0; r < size; ++r)         {             for (c = 0; c < size; ++c)             {                 if (board[r, c] == 0)                     return true;             }         }         r = -1;         c = -1;         return false;     }      // Main recursive function to fill     private static bool TileBoard(int[,] board, int size, int tileId)     {         if (!FindNext0(board, size, out int r, out int c))             return true; // All cells filled successfully          foreach (var shape in TROMINO_SHAPES)         {             if (IsValid(board, r, c, shape, size))             {                 Place(board, r, c, shape, tileId);                 if (TileBoard(board, size, tileId + 1))                     return true; // Found valid solution                 RemoveL(board, r, c, shape);             }         }          return false; // No valid placement, backtrack     }      public static int[,] Tiling(int n, int[] missing)     {         int[,] board = new int[n, n];         board[missing[0], missing[1]] = -1;          if (TileBoard(board, n, 1))             return board;          return new int[,] { { -1 } };     }      public static void Main()     {         int n = 4; // Must be 2^k         int[] missing = { 0, 1 };          int[,] grid = Tiling(n, missing);          int rows = grid.GetLength(0);         int cols = grid.GetLength(1);          for (int i = 0; i < rows; ++i)         {             for (int j = 0; j < cols; ++j)             {                 Console.Write(grid[i, j] + " ");             }             Console.WriteLine();         }     } } 
JavaScript
const TROMINO_SHAPES = [     [[0, 0], [0, 1], [1, 0]], // ┌     [[0, 0], [0, 1], [1, 1]], // ┐     [[0, 0], [1, 0], [1, 1]], // └     [[0, 0], [1, 0], [1, -1]] // ┘ ];  function isValid(board, r, c, shape, size) {     for (const offset of shape) {         const nr = r + offset[0];         const nc = c + offset[1];         if (nr < 0 || nr >= size || nc < 0 || nc >= size || board[nr][nc] !== 0) {             return false;         }     }     return true; }  function place(board, r, c, shape, tileId) {     for (const offset of shape) {         board[r + offset[0]][c + offset[1]] = tileId;     } }  function removeL(board, r, c, shape) {     for (const offset of shape) {         board[r + offset[0]][c + offset[1]] = 0;     } }  function findNextZero(board, size) {     for (let r = 0; r < size; r++) {         for (let c = 0; c < size; c++) {             if (board[r][c] === 0) {                 return [r, c];             }         }     }     return [null, null]; }  function tileBoard(board, size, tileId) {     const [r, c] = findNextZero(board, size);     if (r === null) {         return true; // All cells filled successfully     }      for (const shape of TROMINO_SHAPES) {         if (isValid(board, r, c, shape, size)) {             place(board, r, c, shape, tileId);             if (tileBoard(board, size, tileId + 1)) {                 return true; // Found valid solution             }             removeL(board, r, c, shape); // Backtrack         }     }      return false; // No valid placement }  function tiling(n, missing) {     const board = Array.from({ length: n }, () => Array(n).fill(0));     board[missing[0]][missing[1]] = -1; // Mark missing square      if (tileBoard(board, n, 1)) {         return board;     }     return [[-1]]; }  // Example usage: const n = 4; // Must be 2^k const missing = [0, 1];  const grid = tiling(n, missing); for (const row of grid) {     console.log(row.join(' ')); } 

Output
1 -1 2 2  1 1 3 2  4 3 3 5  4 4 5 5  

Time Complexity: O(4(n^2)), Since each recursive call involves trying 4 possible shapes for every empty cell, the complexity grows exponentially with the board size.
Auxiliary Space: O(n2), space needed to store the board.

[Expected Approach] Using Divide and Conquer algorithm

  • If the board size is 2x2, fill the missing cell with a tile number and return.
  • Divide the board into four quadrants by halving the dimensions of the board (top-left, top-right, bottom-left, bottom-right).
  • Place an L-shaped tile in the three quadrants that do not contain the missing cell, and number the tiles sequentially. Now all four quadrants have a cell not to be filled. So our problem reduces from (n x n) to (n/2) x (n/2)
  • Recursively apply the same process to each of the four smaller sub-boards until the base case (2x2 board) is reached.

Why Above Algorithm Works:
We can prove working of above algorithm using mathematical induction.

Let the input square be of size n x n (or 2k * 2k) where k≥1.

Base Case:
For k=1, the board is a 2×2 square with one missing cell, which can be directly solved by placing an L-shaped tile.

Inductive Hypothesis:
Assume the problem can be solved for a square of size 2k-1 * 2k-1 (n/2 x n/2)

Inductive Step:
For a square of size 2k * 2k divide it into four smaller 2k-1 * 2k-1 squares. Place an L-shaped tile in the center, covering three quadrants, and leave one quadrant with a missing cell. This reduces the problem to solving the four smaller subproblems, each of size 2k-1 * 2k-1, which is possible by the Induction Hypothesis.

The below diagram shows how we get 4 similar subproblems once we place the L shape in middle such that missing tile quadrant is not changed (1st quadrant in the below example), then our problem reduces to the same problem with smaller size as each quadrant now has a cell which is not supposed to be filled.

tiles3

Subproblems for Divide and Conquer{

Illustration:


C++
#include <bits/stdc++.h> using namespace std;  // Tile number to be filled int t = 0;  // Function to place tiles in the sub-grids void place_tile(int x1, int y1, int x2, int y2, int x3, int y3,      vector<vector<int>> &grid){               t++;     grid[x1][y1] = t;     grid[x2][y2] = t;     grid[x3][y3] = t; }  // Recursive function to fill the grid void solve(int sz, int r, int c, vector<vector<int>> &grid){          // Base case: when the grid size is 2x2     if (sz == 2){                  t++;         for (int i = 0; i < sz; i++)             for (int j = 0; j < sz; j++)                 if (grid[r + i][c + j] == 0)                     grid[r + i][c + j] = t;         return;     }      // To store the missing cell's coordinates     int mr, mc;      // Find the missing cell within the current sub-grid     for (int i = r; i < r + sz; i++)         for (int j = c; j < c + sz; j++)             if (grid[i][j] != 0)                 mr = i, mc = j;      // Place tiles based on the quadrant where the missing cell is located     // First quadrant     if (mr < r + sz / 2 && mc < c + sz / 2)         place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                     r + sz / 2 - 1, c + sz / 2, grid);     // Second quadrant     else if (mr >= r + sz / 2 && mc < c + sz / 2)         place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2,                     r + sz / 2 - 1, c + sz / 2 - 1, grid);     // Third quadrant     else if (mr < r + sz / 2 && mc >= c + sz / 2)         place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                     r + sz / 2 - 1, c + sz / 2 - 1, grid);     // Fourth quadrant     else         place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2 - 1,                    r + sz / 2 - 1, c + sz / 2 - 1, grid);      // Recursively solve for the 4 sub-grids     // Top-right     solve(sz / 2, r, c + sz / 2, grid);     // Top-left     solve(sz / 2, r, c, grid);     // Bottom-left     solve(sz / 2, r + sz / 2, c, grid);     // Bottom-right     solve(sz / 2, r + sz / 2, c + sz / 2, grid); } vector<vector<int>> tiling(int n, pair<int, int> missing_cell){          vector<vector<int>> grid(n, vector<int>(n, 0));     grid[missing_cell.first][missing_cell.second]= -1;          solve(n, 0, 0, grid);     return grid;  }   int main(){     int n = 4;     pair<int,int> missing_cell = {0,1};     vector<vector<int>> grid = tiling(n, missing_cell);      for (const auto &row : grid)     {         for (int cell : row)             cout << cell << " ";         cout << endl;     }      return 0; } 
Java
import java.util.*;  public class Main {          // Tile number to be filled     static int t = 0;      // Function to place tiles in the sub-grids     static void place_tile(int x1, int y1, int x2, int y2,                             int x3, int y3, int[][] grid) {         t++;         grid[x1][y1] = t;         grid[x2][y2] = t;         grid[x3][y3] = t;     }      // Recursive function to fill the grid     static void solve(int sz, int r, int c, int[][] grid) {         // Base case: when the grid size is 2x2         if (sz == 2) {             t++;             for (int i = 0; i < sz; i++)                 for (int j = 0; j < sz; j++)                     if (grid[r + i][c + j] == 0)                         grid[r + i][c + j] = t;             return;         }          // To store the missing cell's coordinates         int mr = -1, mc = -1;          // Find the missing cell within the current sub-grid         for (int i = r; i < r + sz; i++)             for (int j = c; j < c + sz; j++)                 if (grid[i][j] != 0){                     mr = i;                      mc = j;                 }                          // First quadrant         if (mr < r + sz / 2 && mc < c + sz / 2)             place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2, grid);         // Second quadrant         else if (mr >= r + sz / 2 && mc < c + sz / 2)             place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2 - 1, grid);         // Third quadrant         else if (mr < r + sz / 2 && mc >= c + sz / 2)             place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2 - 1, grid);         // Fourth quadrant         else             place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2,                         c + sz / 2 - 1, r + sz / 2 - 1, c + sz / 2 - 1, grid);          // Top-right         solve(sz / 2, r, c + sz / 2, grid);         // Top-left         solve(sz / 2, r, c, grid);         // Bottom-left         solve(sz / 2, r + sz / 2, c, grid);         // Bottom-right         solve(sz / 2, r + sz / 2, c + sz / 2, grid);     }      // Function to start the tiling process     static int[][] tiling(int n, int[] missing_cell) {         int[][] grid = new int[n][n];         grid[missing_cell[0]][missing_cell[1]] = -1;         solve(n, 0, 0, grid);         return grid;     }      // Main method to run the program     public static void main(String[] args) {         int n = 4;         int[] missing_cell = {0, 1};         int[][] grid = tiling(n, missing_cell);          for (int[] row : grid) {             for (int cell : row)                 System.out.print(cell + " ");             System.out.println();         }     } } 
Python
# Tile number to be filled t = 0  # Function to place tiles in the sub-grids def place_tile(x1, y1, x2, y2, x3, y3, grid):     global t     t += 1     grid[x1][y1] = t     grid[x2][y2] = t     grid[x3][y3] = t  # Recursive function to fill the grid def solve(sz, r, c, grid):     global t      # Base case: when the grid size is 2x2     if sz == 2:         t += 1         for i in range(sz):             for j in range(sz):                 if grid[r + i][c + j] == 0:                     grid[r + i][c + j] = t         return      # To store the missing cell's coordinates     mr, mc = -1, -1      # Find the missing cell within the current sub-grid     for i in range(r, r + sz):         for j in range(c, c + sz):             if grid[i][j] != 0:                 mr, mc = i, j      # First quadrant     if mr < r + sz // 2 and mc < c + sz // 2:         place_tile(r + sz // 2, c + sz // 2 - 1, r + sz // 2, c + sz // 2,                    r + sz // 2 - 1, c + sz // 2, grid)     # Second quadrant     elif mr >= r + sz // 2 and mc < c + sz // 2:         place_tile(r + sz // 2 - 1, c + sz // 2, r + sz // 2, c + sz // 2,                    r + sz // 2 - 1, c + sz // 2 - 1, grid)     # Third quadrant     elif mr < r + sz // 2 and mc >= c + sz // 2:         place_tile(r + sz // 2, c + sz // 2 - 1, r + sz // 2, c + sz // 2,                    r + sz // 2 - 1, c + sz // 2 - 1, grid)     # Fourth quadrant     else:         place_tile(r + sz // 2 - 1, c + sz // 2, r + sz // 2,                     c + sz // 2 - 1, r + sz // 2 - 1, c + sz // 2 - 1, grid)      # Top-right     solve(sz // 2, r, c + sz // 2, grid)     # Top-left     solve(sz // 2, r, c, grid)     # Bottom-left     solve(sz // 2, r + sz // 2, c, grid)     # Bottom-right     solve(sz // 2, r + sz // 2, c + sz // 2, grid)  # Function to start the tiling process def tiling(n, missing_cell):     grid = [[0 for _ in range(n)] for _ in range(n)]     grid[missing_cell[0]][missing_cell[1]] = -1     solve(n, 0, 0, grid)     return grid  # Main execution n = 4 missing_cell = (0, 1) grid = tiling(n, missing_cell)  for row in grid:     print(' '.join(str(cell) for cell in row)) 
C#
using System; using System.Collections.Generic;  public class Program {     // Tile number to be filled     static int t = 0;      // Function to place tiles in the sub-grids     static void place_tile(int x1, int y1, int x2, int y2, int x3,                            int y3, int[,] grid){                                         t++;         grid[x1, y1] = t;         grid[x2, y2] = t;         grid[x3, y3] = t;     }      // Recursive function to fill the grid     static void solve(int sz, int r, int c, int[,] grid){                  // Base case: when the grid size is 2x2         if (sz == 2){                          t++;             for (int i = 0; i < sz; i++)                 for (int j = 0; j < sz; j++)                     if (grid[r + i, c + j] == 0)                         grid[r + i, c + j] = t;             return;         }          // To store the missing cell's coordinates         int mr = -1, mc = -1;          // Find the missing cell within the current sub-grid         for (int i = r; i < r + sz; i++)             for (int j = c; j < c + sz; j++)                 if (grid[i, j] != 0){                     mr = i;                     mc = j;                 }         // First quadrant         if (mr < r + sz / 2 && mc < c + sz / 2)             place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2, grid);         // Second quadrant         else if (mr >= r + sz / 2 && mc < c + sz / 2)             place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2 - 1, grid);         // Third quadrant         else if (mr < r + sz / 2 && mc >= c + sz / 2)             place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                        r + sz / 2 - 1, c + sz / 2 - 1, grid);         // Fourth quadrant         else             place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2,                         c + sz / 2 - 1, r + sz / 2 - 1, c + sz / 2 - 1, grid);          // Top-right         solve(sz / 2, r, c + sz / 2, grid);         // Top-left         solve(sz / 2, r, c, grid);         // Bottom-left         solve(sz / 2, r + sz / 2, c, grid);         // Bottom-right         solve(sz / 2, r + sz / 2, c + sz / 2, grid);     }      // Function to start the tiling process     static List<int[]> tiling(int n, int[] missing_cell)     {         int[,] grid = new int[n, n];         grid[missing_cell[0], missing_cell[1]] = -1;          solve(n, 0, 0, grid);          List<int[]> result = new List<int[]>();          // Convert 2D array to List<int[]>         for (int i = 0; i < n; i++)         {             int[] row = new int[n];             for (int j = 0; j < n; j++)             {                 row[j] = grid[i, j];             }             result.Add(row);         }          return result;     }      // Main method to run the program     public static void Main()     {         int n = 4;         int[] missing_cell = { 0, 1 };         List<int[]> grid = tiling(n, missing_cell);          foreach (var row in grid)         {             foreach (var cell in row)                 Console.Write(cell + " ");             Console.WriteLine();         }     } } 
JavaScript
// Tile number to be filled let t = 0;  // Function to place tiles in the sub-grids function place_tile(x1, y1, x2, y2, x3, y3, grid) {     t++;     grid[x1][y1] = t;     grid[x2][y2] = t;     grid[x3][y3] = t; }  // Recursive function to fill the grid function solve(sz, r, c, grid) {     // Base case: when the grid size is 2x2     if (sz === 2) {         t++;         for (let i = 0; i < sz; i++) {             for (let j = 0; j < sz; j++) {                 if (grid[r + i][c + j] === 0) {                     grid[r + i][c + j] = t;                 }             }         }         return;     }      // To store the missing cell's coordinates     let mr = -1, mc = -1;      // Find the missing cell within the current sub-grid     for (let i = r; i < r + sz; i++) {         for (let j = c; j < c + sz; j++) {             if (grid[i][j] !== 0) {                 mr = i;                 mc = j;             }         }     }      // First quadrant     if (mr < r + sz / 2 && mc < c + sz / 2)         place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                    r + sz / 2 - 1, c + sz / 2, grid);     // Second quadrant     else if (mr >= r + sz / 2 && mc < c + sz / 2)         place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2,                     r + sz / 2 - 1, c + sz / 2 - 1, grid);     // Third quadrant     else if (mr < r + sz / 2 && mc >= c + sz / 2)         place_tile(r + sz / 2, c + sz / 2 - 1, r + sz / 2, c + sz / 2,                     r + sz / 2 - 1, c + sz / 2 - 1, grid);     // Fourth quadrant     else         place_tile(r + sz / 2 - 1, c + sz / 2, r + sz / 2, c + sz / 2 - 1,                    r + sz / 2 - 1, c + sz / 2 - 1, grid);      // Top-right     solve(sz / 2, r, c + sz / 2, grid);     // Top-left     solve(sz / 2, r, c, grid);     // Bottom-left     solve(sz / 2, r + sz / 2, c, grid);     // Bottom-right     solve(sz / 2, r + sz / 2, c + sz / 2, grid); }  // Function to start the tiling process function tiling(n, missing_cell) {     const grid = Array.from({ length: n }, () => Array(n).fill(0));     grid[missing_cell[0]][missing_cell[1]] = -1;     solve(n, 0, 0, grid);     return grid; }  // Main execution const n = 4; const missing_cell = [0, 1]; const grid = tiling(n, missing_cell);  for (const row of grid) {     console.log(row.join(" ")); } 

Output
3 -1 2 2  3 3 1 2  4 1 1 5  4 4 5 5  

Time Complexity: O(n2), where n is the size of the grid. It recursively divides the grid into four quadrants, and each cell is visited and filled exactly once.
Auxiliary Space: O(n2)



Next Article
Count Inversions of an Array

A

Abhay Rathi
Improve
Article Tags :
  • Divide and Conquer
  • DSA
  • Matrix
Practice Tags :
  • Divide and Conquer
  • Matrix

Similar Reads

  • Divide and Conquer Algorithm
    Divide and Conquer algorithm is a problem-solving strategy that involves. Divide : Break the given problem into smaller non-overlapping problems.Conquer : Solve Smaller ProblemsCombine : Use the Solutions of Smaller Problems to find the overall result.Examples of Divide and Conquer are Merge Sort, Q
    1 min read
  • Introduction to Divide and Conquer Algorithm
    Divide and Conquer Algorithm is a problem-solving technique used to solve problems by dividing the main problem into subproblems, solving them individually and then merging them to find solution to the original problem. Divide and Conquer is mainly useful when we divide a problem into independent su
    9 min read
  • Dynamic Programming vs Divide-and-Conquer
    In this article I’m trying to explain the difference/similarities between dynamic programming and divide and conquer approaches based on two examples: binary search and minimum edit distance (Levenshtein distance).The ProblemWhen I started to learn algorithms it was hard for me to understand the mai
    12 min read
  • Decrease and Conquer
    As divide-and-conquer approach is already discussed, which include following steps: Divide the problem into a number of subproblems that are smaller instances of the same problem. Conquer the sub problems by solving them recursively. If the subproblem sizes are small enough, however, just solve the
    5 min read
  • Advanced master theorem for divide and conquer recurrences
    The Master Theorem is a tool used to solve recurrence relations that arise in the analysis of divide-and-conquer algorithms. The Master Theorem provides a systematic way of solving recurrence relations of the form: T(n) = aT(n/b) + f(n) where a, b, and f(n) are positive functions and n is the size o
    5 min read
  • Some standard Divide and Conquer Algorithms

    • Write program to calculate pow(b, e)
      Given two numbers b and e, the task is to implement a function to compute b^e. Examples: Input: b = 3.00000, e = 5Output: 243.00000 Input: b = 0.55000, e = 3Output: 0.16638 Input: b = -0.67000, e = -7Output: -16.49971 Table of Content [Naive Approach 1] Using Iteration - O(e) Time and O(1) Space[Nai
      10 min read

    • Karatsuba algorithm for fast multiplication using Divide and Conquer algorithm
      Given two binary strings that represent value of two integers, find the product of two strings. For example, if the first bit string is "1100" and second bit string is "1010", output should be 120. For simplicity, let the length of two strings be same and be n. A Naive Approach is to follow the proc
      15+ min read

    • Strassen's Matrix Multiplication
      Given two square matrices arr[][] and brr[][] of order n * n. Your task is to multiply both the matrices and find the resultant matrix. Examples: Input: arr[][] = [ [7, 8], [2, 9] ]brr[][] = [ [14, 5], [5, 18] ]Output: [ [138, 179], [73, 172] ] Input: arr[][] = [ [17, 4], [17, 16] ]brr[][] = [ [9, 2
      15+ min read

    • Convex Hull using Divide and Conquer Algorithm
      In computational geometry, a convex hull is the smallest convex polygon that contains a given set of points. It is a fundamental concept with applications in various fields such as computer graphics, robotics, and image processing. Importance of Convex Hull:Convex hulls are important in computationa
      15 min read

    • Quickhull Algorithm for Convex Hull
      Given a set of points, a Convex hull is the smallest convex polygon containing all the given points. Input : points[] = {{0, 3}, {1, 1}, {2, 2}, {4, 4}, {0, 0}, {1, 2}, {3, 1}, {3, 3}};Output : The points in convex hull are: (0, 0) (0, 3) (3, 1) (4, 4)Input : points[] = {{0, 3}, {1, 1}Output : Not P
      14 min read

    Binary Search based problems

    • Peak Element in Array
      Given an array arr[] where no two adjacent elements are same, find the index of a peak element. An element is considered to be a peak element if it is strictly greater than its adjacent elements. If there are multiple peak elements, return the index of any one of them. Note: Consider the element bef
      13 min read

    • Check for Majority Element in a sorted array
      Given an array arr of N elements, A majority element in an array arr of size N is an element that appears more than N/2 times in the array. The task is to write a function say isMajority() that takes an array (arr[] ), array’s size (n) and a number to be searched (x) as parameters and returns true i
      15+ min read

    • K-th Element of Merged Two Sorted Arrays
      Given two sorted arrays of sizes m and n respectively, the task is to find the element that would be at the k-th position in the final sorted array formed by merging these two arrays. Examples: Input: a[] = [2, 3, 6, 7, 9], b[] = [1, 4, 8, 10], k = 5Output: 6Explanation: The final sorted array is [1
      15+ min read

    • Find the number of zeroes
      Given an array of 1s and 0s which has all 1s first followed by all 0s. Find the number of 0s. Count the number of zeroes in the given array.Examples : Input: arr[] = {1, 1, 1, 1, 0, 0} Output: 2 Input: arr[] = {1, 0, 0, 0, 0} Output: 4 Input: arr[] = {0, 0, 0} Output: 3 Input: arr[] = {1, 1, 1, 1} O
      12 min read

    • Rotation Count in a Rotated Sorted array
      Given an array arr[] having distinct numbers sorted in increasing order and the array has been right rotated (i.e, the last element will be cyclically shifted to the starting position of the array) k number of times, the task is to find the value of k. Examples: Input: arr[] = {15, 18, 2, 3, 6, 12}O
      13 min read

    • Unbounded Binary Search Example (Find the point where a monotonically increasing function becomes positive first time)
      Given a function 'int f(unsigned int x)' which takes a non-negative integer 'x' as input and returns an integer as output. The function is monotonically increasing with respect to the value of x, i.e., the value of f(x+1) is greater than f(x) for every input x. Find the value 'n' where f() becomes p
      11 min read

    • Median of two Sorted Arrays of Different Sizes
      Given two sorted arrays, a[] and b[], the task is to find the median of these sorted arrays. Assume that the two sorted arrays are merged and then median is selected from the combined array. This is an extension of Median of two sorted arrays of equal size problem. Here we handle arrays of unequal s
      15+ min read

    • The Painter's Partition Problem using Binary Search
      Given an array arr[] and k, where the array represents the boards and each element of the given array represents the length of each board. k numbers of painters are available to paint these boards. Consider that each unit of a board takes 1 unit of time to paint.The task is to find the minimum time
      10 min read

    Some practice problems on Divide and Conquer algorithm

    • Program for Square Root of Integer
      Given a positive integer n, find its square root. If n is not a perfect square, then return floor of √n. Examples : Input: n = 4Output: 2Explanation: The square root of 4 is 2. Input: n = 11Output: 3Explanation: The square root of 11 lies in between 3 and 4 so floor of the square root is 3. Table of
      13 min read

    • Maximum and minimum of an array using minimum number of comparisons
      Given an array of size N. The task is to find the maximum and the minimum element of the array using the minimum number of comparisons. Examples: Input: arr[] = {3, 5, 4, 1, 9}Output: Minimum element is: 1 Maximum element is: 9 Input: arr[] = {22, 14, 8, 17, 35, 3}Output: Minimum element is: 3 Maxim
      15+ min read

    • Find frequency of each element in a limited range array in less than O(n) time
      Given a sorted array arr[] of positive integers, the task is to find the frequency for each element in the array. Assume all elements in the array are less than some constant M Note: Do this without traversing the complete array. i.e. expected time complexity is less than O(n) Examples: Input: arr[]
      10 min read

    • Tiling Problem - L Shaped
      Given an n×n board (where n = 2k and k≥1), with one missing cell, the task is to fill the remaining cells using L-shaped tiles. An L-shaped tile covers 3 cells in a 2x2 grid, with one cell missing. You need to tile the entire board using the L-shaped tiles, ensuring that the missing cell remains unc
      15+ min read

    • Count Inversions of an Array
      Given an integer array arr[] of size n, find the inversion count in the array. Two array elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j. Note: Inversion Count for an array indicates that how far (or close) the array is from being sorted. If the array is already sorte
      15+ min read

    • The Skyline Problem | Set-1
      Given n rectangular buildings in a 2-dimensional city, compute the skyline of these buildings, eliminating hidden lines. The main task is to view buildings from a side and remove all sections that are not visible. All buildings share a common bottom and every building is represented by a triplet (le
      14 min read

    • Search in a Row-wise and Column-wise Sorted 2D Array using Divide and Conquer algorithm
      Given an n x n matrix, where every row and column is sorted in increasing order. Given a key, how to decide whether this key is in the matrix. Input: x = 62, mat[][] = [[3, 30, 38], [20, 52, 54], [35, 60, 69]]Output: falseExplanation: 62 is not present in the matrix. Input: x = 30, mat[][] = [[3, 30
      7 min read

    • Allocate Minimum Pages
      Given an array arr[] and an integer k, where arr[i] denotes the number of pages of a book and k denotes total number of students. All the books need to be allocated to k students in contiguous manner, with each student getting at least one book. The task is to minimize the maximum number of pages al
      15+ min read

geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences