Largest subset of rectangles such that no rectangle fit in any other rectangle

Given height and width of N rectangles. The task is to find the size of the largest subset such that no pair of rectangles fit within each other. Note that if H1 ? H2 and W1 ? W2 then rectangle 1 fits inside rectangle 2.Â
Examples:Â
Input: arr[] = {{1, 3}, {2, 2}, {1, 3}}Â
Output: 2Â
The required sub-set is {{1, 3}, {2, 2}}Â
{1, 3} is included only once as it can fit in {1, 3}Input: arr[] = {{1, 5}, {2, 4}, {1, 1}, {3, 3}}Â
Output: 3Â Â
Approach: The above problem can be solved using Dynamic Programming and sorting. Initially, we can sort the N pairs on the basis of heights. A recursive function can be written where there will be two states.
The first state being, if the present rectangle does not fit in the previous rectangle or the vice versa, then we call for the next state with the present rectangle being the previous rectangle and moving to the next rectangle.Â
dp[present][previous] = max(dp[present][previous], 1 + dp[present + 1][present])Â
If it does fit in, we call the next state with the previous rectangle and moving to the next rectangle.Â
dp[present][previous] = max(dp[present][previous], dp[present + 1][previous])Â
Memoization can be further used to avoid repetitively the same states being called.Â
Below is the implementation of the above approach:
C++
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std;#define N 10int dp[N][N];Â
// Recursive function to get the largest subsetint findLongest(pair<int, int> a[], int n,                int present, int previous){    // Base case when it exceeds    if (present == n) {        return 0;    }Â
    // If the state has been visited previously    else if (previous != -1) {        if (dp[present][previous] != -1)            return dp[present][previous];    }Â
    // Initialize    int ans = 0;Â
    // No elements in subset yet    if (previous == -1) {Â
        // First state which includes current index        ans = 1 + findLongest(a, n,                              present + 1, present);Â
        // Second state which does not include current index        ans = max(ans, findLongest(a, n,                                   present + 1, previous));    }    else {        int h1 = a[previous].first;        int h2 = a[present].first;        int w1 = a[previous].second;        int w2 = a[present].second;Â
        // If the rectangle fits in, then do not include        // the current index in subset        if ((h1 <= h2 && w1 <= w2)) {            ans = max(ans, findLongest(a, n,                                       present + 1, previous));        }        else {Â
            // First state which includes current index            ans = 1 + findLongest(a, n,                                  present + 1, present);Â
            // Second state which does not include current index            ans = max(ans, findLongest(a, n,                                       present + 1, previous));        }    }Â
    return dp[present][previous] = ans;}Â
// Function to get the largest subsetint getLongest(pair<int, int> a[], int n){Â Â Â Â // Initialize the DP table with -1Â Â Â Â memset(dp, -1, sizeof dp);Â
    // Sort the array    sort(a, a + n);Â
    // Get the answer    int ans = findLongest(a, n, 0, -1);    return ans;}Â
// Driver codeint main(){Â
    // (height, width) pairs    pair<int, int> a[] = { { 1, 5 },                           { 2, 4 },                           { 1, 1 },                           { 3, 3 } };    int n = sizeof(a) / sizeof(a[0]);Â
    cout << getLongest(a, n);Â
    return 0;} |
Java
// Java implementation of the above approach.import java.io.*;import java.util.Arrays;import java.util.Comparator;Â
public class GFG {Â
    // A function to sort the 2D array by column number.    static void Sort(int[][] array, final int columnNumber)    {        Arrays.sort(array, new Comparator<int[]>() {            @Override            public int compare(int[] first, int[] second)            {                if (columnNumber >= 1                    && first[columnNumber - 1]                           > second[columnNumber - 1])                    return 1;                else                    return -1;            }        });    }Â
    // Recursive function to get the largest subset    static int findLongest(int[][] a, int n, int present,                           int previous, int[][] dp, int N)    {        // Base case when it exceeds        if (present == n) {            return 0;        }Â
        // If the state has been visited previously        else if (previous != -1) {            if (dp[present][previous] != -1)                return dp[present][previous];        }Â
        // Initialize        int ans = 0;Â
        // No elements in subset yet        if (previous == -1) {Â
            // First state which includes current index            ans = 1                  + findLongest(a, n, present + 1, present,                                dp, N);Â
            // Second state which does not include current            // index            ans = Math.max(ans,                           findLongest(a, n, present + 1,                                       previous, dp, N));        }        else {            int h1 = a[previous][0];            int h2 = a[present][0];            int w1 = a[previous][1];            int w2 = a[present][1];Â
            // If the rectangle fits in, then do not include            // the current index in subset            if ((h1 <= h2 && w1 <= w2)) {                ans = Math.max(                    ans, findLongest(a, n, present + 1,                                     previous, dp, N));            }            else {Â
                // First state which includes current index                ans = 1                      + findLongest(a, n, present + 1,                                    present, dp, N);Â
                // Second state which does not include                // current index                ans = Math.max(                    ans, findLongest(a, n, present + 1,                                     previous, dp, N));            }        }Â
        if (present >= 0 && previous >= 0) {            return dp[present][previous] = ans;        }        return ans;    }Â
    // Function to get the largest subset    static int getLongest(int[][] a, int n)    {        int N = 10;        int[][] dp = new int[N + 1][N + 1];        // Initialize the DP table with -1        for (int i = 0; i < N + 1; i++) {            for (int j = 0; j < N + 1; j++) {                dp[i][j] = -1;            }        }Â
        // Sort the array        Sort(a, 0);Â
        // Get the answer        int ans = findLongest(a, n, 0, -1, dp, N);        return ans;    }Â
    // Driver code    // (height, width) pairs    public static void main(String[] args)    {        int[][] a            = { { 1, 5 }, { 2, 4 }, { 1, 1 }, { 3, 3 } };        int n = a.length;        System.out.println(getLongest(a, n));    }}Â
  // The code is contributed by Gautam goel (guatamgoel962) |
Python3
# Python3 implementation of the approachÂ
# Recursive function to get the# largest subsetdef findLongest(a, n, present, previous):Â
    # Base case when it exceeds    if present == n:        return 0         # If the state has been visited     # previously    elif previous != -1:         if dp[present][previous] != -1:            return dp[present][previous]Â
    # Initialize    ans = 0Â
    # No elements in subset yet    if previous == -1:Â
        # First state which includes         # current index        ans = 1 + findLongest(a, n, present + 1,                                    present)Â
        # Second state which does not         # include current index        ans = max(ans, findLongest(a, n, present + 1,                                          previous))         else:        h1 = a[previous][0]        h2 = a[present][0]        w1 = a[previous][1]        w2 = a[present][1]Â
        # If the rectangle fits in, then do         # not include the current index in subset        if h1 <= h2 and w1 <= w2:             ans = max(ans, findLongest(a, n, present + 1,                                              previous))                 else: Â
            # First state which includes             # current index            ans = 1 + findLongest(a, n, present + 1,                                         present)Â
            # Second state which does not             # include current index            ans = max(ans, findLongest(a, n, present + 1,                                              previous))Â
    dp[present][previous] = ans    return ansÂ
# Function to get the largest subsetdef getLongest(a, n):Â
    # Sort the array    a.sort()Â
    # Get the answer    ans = findLongest(a, n, 0, -1)    return ansÂ
# Driver codeif __name__ == "__main__":Â
    # (height, width) pairs    a = [[1, 5], [2, 4], [1, 1], [3, 3]]          N = 10         # Initialize the DP table with -1    dp = [[-1 for i in range(N)]               for j in range(N)]Â
    n = len(a)    print(getLongest(a, n))Â
# This code is contributed# by Rituraj Jain |
C#
using System;using System.Linq;class GFG {  // A function to sort the 2D array by column number.  static void Sort(int[][] array, int columnNumber)  {    Array.Sort(array, (first, second) = > {      if (columnNumber >= 1          && first[columnNumber - 1]          > second[columnNumber - 1]) {        return 1;      }      else {        return -1;      }    });  }Â
  // Recursive function to get the largest subset  static int findLongest(int[][] a, int n, int present,                         int previous, int[][] dp, int N)  {    // Base case when it exceeds    if (present == n) {      return 0;    }Â
    // If the state has been visited previously    else if (previous != -1) {      if (dp[present][previous] != -1)        return dp[present][previous];    }Â
    // Initialize    int ans = 0;Â
    // No elements in subset yet    if (previous == -1) {Â
      // First state which includes current index      ans = 1        + findLongest(a, n, present + 1, present,                      dp, N);Â
      // Second state which does not include current      // index      ans = Math.Max(ans,                     findLongest(a, n, present + 1,                                 previous, dp, N));    }    else {      int h1 = a[previous][0];      int h2 = a[present][0];      int w1 = a[previous][1];      int w2 = a[present][1];Â
      // If the rectangle fits in, then do not include      // the current index in subset      if ((h1 <= h2 && w1 <= w2)) {        ans = Math.Max(          ans, findLongest(a, n, present + 1,                           previous, dp, N));      }      else {Â
        // First state which includes current index        ans = 1          + findLongest(a, n, present + 1,                        present, dp, N);Â
        // Second state which does not include        // current index        ans = Math.Max(          ans, findLongest(a, n, present + 1,                           previous, dp, N));      }    }Â
    if (present >= 0 && previous >= 0) {      return dp[present][previous] = ans;    }    return ans;  }Â
  // Function to get the largest subset  static int getLongest(int[][] a, int n)  {    int N = 10;    int[][] dp = new int[N + 1][];    for (int i = 0; i <= N; i++)      dp[i] = Enumerable.Repeat(-1, N + 1).ToArray();Â
    // Sort the array    Sort(a, 0);Â
    // Get the answer    int ans = findLongest(a, n, 0, -1, dp, N);    return ans;  }Â
  // Driver code  // (height, width) pairs  public static void Main(string[] args)  {    int[][] a = new int[4][];    a[0] = new int[] { 1, 5 };    a[1] = new int[] { 2, 4 };    a[2] = new int[] { 1, 1 };    a[3] = new int[] { 3, 3 };    int n = a.Length;    Console.WriteLine(getLongest(a, n));  }} |
Javascript
<script>Â
// JavaScript implementation of the approachvar N = 10;var dp = Array.from(Array(N), ()=>Array(N).fill(-1));Â
// Recursive function to get the largest subsetfunction findLongest(a, n, present, previous){    // Base case when it exceeds    if (present == n) {        return 0;    }Â
    // If the state has been visited previously    else if (previous != -1) {        if (dp[present][previous] != -1)            return dp[present][previous];    }Â
    // Initialize    var ans = 0;Â
    // No elements in subset yet    if (previous == -1) {Â
        // First state which includes current index        ans = 1 + findLongest(a, n,                              present + 1, present);Â
        // Second state which does not include current index        ans = Math.max(ans, findLongest(a, n,                                   present + 1, previous));    }    else {        var h1 = a[previous][0];        var h2 = a[present][0];        var w1 = a[previous][1];        var w2 = a[present][1];Â
        // If the rectangle fits in, then do not include        // the current index in subset        if ((h1 <= h2 && w1 <= w2)) {            ans = Math.max(ans, findLongest(a, n,                                       present + 1, previous));        }        else {Â
            // First state which includes current index            ans = 1 + findLongest(a, n,                                  present + 1, present);Â
            // Second state which does not include current index            ans = Math.max(ans, findLongest(a, n,                                       present + 1, previous));        }    }Â
    return dp[present][previous] = ans;}Â
// Function to get the largest subsetfunction getLongest(a, n){Â Â Â Â // Initialize the DP table with -1Â Â Â Â dp = Array.from(Array(N), ()=>Array(N).fill(-1));Â
    // Sort the array    a.sort((a,b)=>a-b);Â
    // Get the answer    var ans = findLongest(a, n, 0, -1);    return ans;}Â
// Driver code// (height, width) pairsvar a = [ [ 1, 5 ],          [ 2, 4 ],          [ 1, 1 ],          [ 3, 3 ] ];var n = a.length;document.write( getLongest(a, n));Â
Â
</script> |
3
Â
Time Complexity: O(N*N), where dp operations taking N*N timeÂ
Auxiliary Space: O(N*N), dp array made of two states each having N space, i.e. N*N
New approach:- Another approach to solve this problem is by using greedy algorithm. We can sort the rectangles in decreasing order of their widths, so that the widest rectangle is considered first. Then, we can add the widest rectangle to the subset and remove all the rectangles that it can contain from the remaining set of rectangles. We can repeat this process with the remaining set of rectangles until we can’t find any more rectangles that fit in the current subset.
Here’s the implementation of the above approach:
C++
#include <iostream>#include <vector>#include <algorithm>Â
using namespace std;Â
int getLongest(vector<pair<int, int>>& arr) {    // sort the rectangles in decreasing order of their widths    sort(arr.begin(), arr.end(), [](const pair<int, int>& a, const pair<int, int>& b) {        return a.second > b.second;    });Â
    // initialize the subset with the widest rectangle    vector<pair<int, int>> subset = {arr[0]};Â
    // iterate over the remaining rectangles    for (int i = 1; i < arr.size(); i++) {        // check if the current rectangle can fit in any rectangle in the subset        bool fits = false;        for (const auto& rect : subset) {            if (arr[i].first <= rect.first && arr[i].second <= rect.second) {                fits = true;                break;            }        }        if (!fits) {            subset.push_back(arr[i]);        }    }Â
    // return the size of the largest subset    return subset.size();}Â
int main() {Â Â Â Â vector<pair<int, int>> arr = {{1, 3}, {2, 2}, {1, 3}};Â Â Â Â cout << getLongest(arr) << endl;Â // output: 2Â
    arr = {{1, 5}, {2, 4}, {1, 1}, {3, 3}};    cout << getLongest(arr) << endl; // output: 3Â
    return 0;} |
Java
import java.util.*;Â
public class Main {    public static int getLongest(int[][] arr)    {        // sort the rectangles in decreasing order of their        // widths        Arrays.sort(arr, new Comparator<int[]>() {            @Override public int compare(int[] a, int[] b)            {                return Integer.compare(b[1], a[1]);            }        });Â
        // initialize the subset with the widest rectangle        List<int[]> subset = new ArrayList<>();        subset.add(arr[0]);Â
        // iterate over the remaining rectangles        for (int i = 1; i < arr.length; i++) {            int[] rect = arr[i];            // check if the current rectangle can fit in any            // rectangle in the subset            boolean canFit = false;            for (int[] r : subset) {                if (rect[0] <= r[0] && rect[1] <= r[1]) {                    canFit = true;                    break;                }            }            if (!canFit) {                subset.add(rect);            }        }Â
        // return the size of the largest subset        return subset.size();    }Â
    public static void main(String[] args)    {        int[][] arr1 = { { 1, 3 }, { 2, 2 }, { 1, 3 } };        System.out.println(getLongest(arr1)); // output: 2Â
        int[][] arr2            = { { 1, 5 }, { 2, 4 }, { 1, 1 }, { 3, 3 } };        System.out.println(getLongest(arr2)); // output: 3    }} |
Python
def getLongest(arr):    # sort the rectangles in decreasing order of their widths    arr.sort(key=lambda x: x[1], reverse=True)         # initialize the subset with the widest rectangle    subset = [arr[0]]         # iterate over the remaining rectangles    for rect in arr[1:]:        # check if the current rectangle can fit in any rectangle in the subset        if not any(rect[0] <= r[0] and rect[1] <= r[1] for r in subset):            subset.append(rect)         # return the size of the largest subset    return len(subset)Â
# example usagearr = [(1, 3), (2, 2), (1, 3)]print(getLongest(arr))Â # output: 2Â
arr = [(1, 5), (2, 4), (1, 1), (3, 3)]print(getLongest(arr))Â # output: 3 |
C#
using System;using System.Collections.Generic;using System.Linq;Â
class Program{    static int GetLongest(List<Tuple<int, int>> arr)    {        // sort the rectangles in decreasing order of their widths        arr.Sort((a, b) => b.Item2.CompareTo(a.Item2));Â
        // initialize the subset with the widest rectangle        List<Tuple<int, int>> subset = new List<Tuple<int, int>> { arr[0] };Â
        // iterate over the remaining rectangles        foreach (var rect in arr.Skip(1))        {            // check if the current rectangle can fit in any rectangle in the subset            if (!subset.Any(r => rect.Item1 <= r.Item1 && rect.Item2 <= r.Item2))            {                subset.Add(rect);            }        }Â
        // return the size of the largest subset        return subset.Count;    }Â
    static void Main(string[] args)    {        List<Tuple<int, int>> arr = new List<Tuple<int, int>>        {            Tuple.Create(1, 3),            Tuple.Create(2, 2),            Tuple.Create(1, 3)        };        Console.WriteLine(GetLongest(arr)); // output: 2Â
        arr = new List<Tuple<int, int>>        {            Tuple.Create(1, 5),            Tuple.Create(2, 4),            Tuple.Create(1, 1),            Tuple.Create(3, 3)        };        Console.WriteLine(GetLongest(arr)); // output: 3    }} |
Javascript
function getLongest(arr) {    // sort the rectangles in decreasing order of their widths    arr.sort((a, b) => b[1] - a[1]);Â
    // initialize the subset with the widest rectangle    let subset = [arr[0]];Â
    // iterate over the remaining rectangles    for (let i = 1; i < arr.length; i++) {        const rect = arr[i];        // check if the current rectangle can fit in any rectangle in the subset        if (!subset.some(r => rect[0] <= r[0] && rect[1] <= r[1])) {            subset.push(rect);        }    }Â
    // return the size of the largest subset    return subset.length;}Â
// example usageconst arr1 = [    [1, 3],    [2, 2],    [1, 3]];console.log(getLongest(arr1)); // output: 2Â
const arr2 = [    [1, 5],    [2, 4],    [1, 1],    [3, 3]];console.log(getLongest(arr2)); // output: 3 |
2 3
Time Complexity:- The time complexity of the above approach is O(n^2), where n is the number of rectangles. However, since we are sorting the rectangles based on their widths, the actual running time may be lower in practice.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



