Open In App

# 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:
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 ``using` `namespace` `std;``#define N 10``int` `dp[N][N];` `// Recursive function to get the largest subset``int` `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 subset``int` `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 code``int` `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 subset``def` `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 subset``def` `getLongest(a, n):` `    ``# Sort the array``    ``a.sort()` `    ``# Get the answer``    ``ans ``=` `findLongest(a, n, ``0``, ``-``1``)``    ``return` `ans` `# Driver code``if` `__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

 ``

Output:

`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 ``#include ``#include ` `using` `namespace` `std;` `int` `getLongest(vector>& 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> 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> 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 usage``arr ``=` `[(``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> 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> subset = ``new` `List> { 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> arr = ``new` `List>``        ``{``            ``Tuple.Create(1, 3),``            ``Tuple.Create(2, 2),``            ``Tuple.Create(1, 3)``        ``};``        ``Console.WriteLine(GetLongest(arr));  ``// output: 2` `        ``arr = ``new` `List>``        ``{``            ``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 usage``const 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`

Output

```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.