<p>What's the most efficient algorithm to find the rectangle with the largest area which will fit in the empty space?</p>

<p>Let's say the screen looks like this ('#' represents filled area):</p>

<pre><code>....................
..............######
##..................
.................###
.................###
#####...............
#####...............
#####...............
</code></pre>

<p>A probable solution is:</p>

<pre><code>....................
..............######
##...++++++++++++...
.....++++++++++++###
.....++++++++++++###
#####++++++++++++...
#####++++++++++++...
#####++++++++++++...
</code></pre>

<p>Normally I'd enjoy figuring out a solution. Although this time I'd like to avoid wasting time fumbling around on my own since this has a practical use for a project I'm working on. Is there a well-known solution?</p>

<p><strong>Shog9</strong> wrote:</p>

<blockquote>
  <p>Is your input an array (as implied by the other responses), or a list of occlusions in the form of arbitrarily sized, positioned rectangles (as might be the case in a windowing system when dealing with window positions)?</p>
</blockquote>

<p>Yes, I have a structure which keeps track of a set of windows placed on the screen. I also have a grid which keeps track of all the areas between each edge, whether they are empty or filled, and the pixel position of their left or top edge. I think there is some modified form which would take advantage of this property. Do you know of any?</p>

[{'answer_id': 7250, 'author': 'Mark Renouf', 'author_id': 758, 'author_profile': 'https://Stackoverflow.com/users/758', 'pm_score': 2, 'selected': False, 'text': "<p>@lassevk</p>\n\n<pre><code>    // 4. Outer double-for-loop to consider all possible positions \n    //    for topleft corner. \n    for (int i=0; i &lt; M; i++) {\n      for (int j=0; j &lt; N; j++) {\n\n        // 2.1 With (i,j) as topleft, consider all possible bottom-right corners. \n\n        for (int a=i; a &lt; M; a++) {\n          for (int b=j; b &lt; N; b++) {\n</code></pre>\n\n<p>HAHA... O(m2 n2).. That's probably what I would have come up with.</p>\n\n<p>I see they go on to develop optmizations... looks good, I'll have a read.</p>\n"}, {'answer_id': 7258, 'author': 'Mark Renouf', 'author_id': 758, 'author_profile': 'https://Stackoverflow.com/users/758', 'pm_score': 6, 'selected': True, 'text': '<p>@lassevk</p>\n\n<p>I found the referenced article, from DDJ: <a href="http://www.ddj.com/184410529" rel="noreferrer">The Maximal Rectangle Problem</a></p>\n'}, {'answer_id': 20039017, 'author': 'Daveed V.', 'author_id': 2308239, 'author_profile': 'https://Stackoverflow.com/users/2308239', 'pm_score': 5, 'selected': False, 'text': '<p>I\'m the author of that Dr. Dobb\'s article and get occasionally asked about an implementation.  Here is a simple one in C:</p>\n<pre class="lang-c prettyprint-override"><code>#include &lt;assert.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n\ntypedef struct {\n  int one;\n  int two;\n} Pair;\n\nPair best_ll = { 0, 0 };\nPair best_ur = { -1, -1 };\nint best_area = 0;\n\nint *c; /* Cache */\nPair *s; /* Stack */\nint top = 0; /* Top of stack */\n\nvoid push(int a, int b) {\n  s[top].one = a;\n  s[top].two = b;\n  ++top;\n}\n\nvoid pop(int *a, int *b) {\n  --top;\n  *a = s[top].one;\n  *b = s[top].two;\n}\n\n\nint M, N; /* Dimension of input; M is length of a row. */\n\nvoid update_cache() {\n  int m;\n  char b;\n  for (m = 0; m!=M; ++m) {\n    scanf(&quot; %c&quot;, &amp;b);\n    fprintf(stderr, &quot; %c&quot;, b);\n    if (b==\'0\') {\n      c[m] = 0;\n    } else { ++c[m]; }\n  }\n  fprintf(stderr, &quot;\\n&quot;);\n}\n\n\nint main() {\n  int m, n;\n  scanf(&quot;%d %d&quot;, &amp;M, &amp;N);\n  fprintf(stderr, &quot;Reading %dx%d array (1 row == %d elements)\\n&quot;, M, N, M);\n  c = (int*)malloc((M+1)*sizeof(int));\n  s = (Pair*)malloc((M+1)*sizeof(Pair));\n  for (m = 0; m!=M+1; ++m) { c[m] = s[m].one = s[m].two = 0; }\n  /* Main algorithm: */\n  for (n = 0; n!=N; ++n) {\n    int open_width = 0;\n    update_cache();\n    for (m = 0; m!=M+1; ++m) {\n      if (c[m]&gt;open_width) { /* Open new rectangle? */\n        push(m, open_width);\n        open_width = c[m];\n      } else /* &quot;else&quot; optional here */\n      if (c[m]&lt;open_width) { /* Close rectangle(s)? */\n        int m0, w0, area;\n        do {\n          pop(&amp;m0, &amp;w0);\n          area = open_width*(m-m0);\n          if (area&gt;best_area) {\n            best_area = area;\n            best_ll.one = m0; best_ll.two = n;\n            best_ur.one = m-1; best_ur.two = n-open_width+1;\n          }\n          open_width = w0;\n        } while (c[m]&lt;open_width);\n        open_width = c[m];\n        if (open_width!=0) {\n          push(m0, w0);\n        }\n      }\n    }\n  }\n  fprintf(stderr, &quot;The maximal rectangle has area %d.\\n&quot;, best_area);\n  fprintf(stderr, &quot;Location: [col=%d, row=%d] to [col=%d, row=%d]\\n&quot;,\n                  best_ll.one+1, best_ll.two+1, best_ur.one+1, best_ur.two+1);\n  return 0;\n}\n</code></pre>\n<p>It takes its input from the console.  You could e.g. pipe this file to it:</p>\n<pre><code>16 12\n0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0\n0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0\n0 0 0 1 1 0 0 1 0 0 0 1 1 0 1 0\n0 0 0 1 1 0 1 1 1 0 1 1 1 0 1 0\n0 0 0 0 1 1 * * * * * * 0 0 1 0\n0 0 0 0 0 0 * * * * * * 0 0 1 0\n0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0\n0 0 1 0 0 0 0 1 0 0 1 1 1 0 1 0 \n0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 \n0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0\n0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0\n0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0\n</code></pre>\n<p>And after printing its input, it will output:</p>\n<pre><code>The maximal rectangle has area 12.\nLocation: [col=7, row=6] to [col=12, row=5]\n</code></pre>\n<p>The implementation above is nothing fancy of course, but it\'s very close to the explanation in the Dr. Dobb\'s article and should be easy to translate to whatever is needed.</p>\n'}, {'answer_id': 37994342, 'author': 'Spike2050', 'author_id': 1167159, 'author_profile': 'https://Stackoverflow.com/users/1167159', 'pm_score': 2, 'selected': False, 'text': '<p>I implemented the solution of Dobbs in Java.</p>\n\n<p>No warranty for anything.</p>\n\n<pre><code>package com.test;\n\nimport java.util.Stack;\n\npublic class Test {\n\n    public static void main(String[] args) {\n        boolean[][] test2 = new boolean[][] { new boolean[] { false, true, true, false },\n                new boolean[] { false, true, true, false }, new boolean[] { false, true, true, false },\n                new boolean[] { false, true, false, false } };\n        solution(test2);\n    }\n\n    private static class Point {\n        public Point(int x, int y) {\n            this.x = x;\n            this.y = y;\n        }\n\n        public int x;\n        public int y;\n    }\n\n    public static int[] updateCache(int[] cache, boolean[] matrixRow, int MaxX) {\n        for (int m = 0; m &lt; MaxX; m++) {\n            if (!matrixRow[m]) {\n                cache[m] = 0;\n            } else {\n                cache[m]++;\n            }\n        }\n        return cache;\n    }\n\n    public static void solution(boolean[][] matrix) {\n        Point best_ll = new Point(0, 0);\n        Point best_ur = new Point(-1, -1);\n        int best_area = 0;\n\n        final int MaxX = matrix[0].length;\n        final int MaxY = matrix.length;\n\n        Stack&lt;Point&gt; stack = new Stack&lt;Point&gt;();\n        int[] cache = new int[MaxX + 1];\n\n        for (int m = 0; m != MaxX + 1; m++) {\n            cache[m] = 0;\n        }\n\n        for (int n = 0; n != MaxY; n++) {\n            int openWidth = 0;\n            cache = updateCache(cache, matrix[n], MaxX);\n            for (int m = 0; m != MaxX + 1; m++) {\n                if (cache[m] &gt; openWidth) {\n                    stack.push(new Point(m, openWidth));\n                    openWidth = cache[m];\n                } else if (cache[m] &lt; openWidth) {\n                    int area;\n                    Point p;\n                    do {\n                        p = stack.pop();\n                        area = openWidth * (m - p.x);\n                        if (area &gt; best_area) {\n                            best_area = area;\n                            best_ll.x = p.x;\n                            best_ll.y = n;\n                            best_ur.x = m - 1;\n                            best_ur.y = n - openWidth + 1;\n                        }\n                        openWidth = p.y;\n                    } while (cache[m] &lt; openWidth);\n                    openWidth = cache[m];\n                    if (openWidth != 0) {\n                        stack.push(p);\n                    }\n                }\n            }\n        }\n\n        System.out.printf("The maximal rectangle has area %d.\\n", best_area);\n        System.out.printf("Location: [col=%d, row=%d] to [col=%d, row=%d]\\n", best_ll.x + 1, best_ll.y + 1,\n                best_ur.x + 1, best_ur.y + 1);\n    }\n\n}\n</code></pre>\n'}, {'answer_id': 55718418, 'author': 'Primusa', 'author_id': 8112138, 'author_profile': 'https://Stackoverflow.com/users/8112138', 'pm_score': 3, 'selected': False, 'text': '<p>I am the author of the <a href="https://leetcode.com/problems/maximal-rectangle/solution/" rel="noreferrer">Maximal Rectangle Solution</a> on LeetCode, which is what this answer is based on. </p>\n\n<p>Since the stack-based solution has already been discussed in the other answers, I would like to present an optimal <code>O(NM)</code> dynamic programming solution which originates from user <a href="https://leetcode.com/morrischen2008/" rel="noreferrer">morrischen2008</a>.</p>\n\n<p><strong>Intuition</strong></p>\n\n<p>Imagine an algorithm where for each point we computed a rectangle by doing the following:</p>\n\n<ul>\n<li><p>Finding the maximum height of the rectangle by iterating upwards until a filled area is reached</p></li>\n<li><p>Finding the maximum width of the rectangle by iterating outwards left and right until a height that doesn\'t accommodate the maximum height of the rectangle</p></li>\n</ul>\n\n<p>For example finding the rectangle defined by the yellow point:\n<a href="https://i.stack.imgur.com/gmkcw.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/gmkcw.gif" alt="enter image description here"></a></p>\n\n<p>We know that the maximal rectangle must be one of the rectangles constructed in this manner (the max rectangle must have a point on its base where the next filled square is <em>height</em> above that point).</p>\n\n<p>For each point we define some variables:</p>\n\n<p><code>h</code> - the height of the rectangle defined by that point</p>\n\n<p><code>l</code> - the left bound of the rectangle defined by that point</p>\n\n<p><code>r</code> - the right bound of the rectangle defined by that point</p>\n\n<p>These three variables uniquely define the rectangle at that point. We can compute the area of this rectangle with <code>h * (r - l)</code>. The global maximum of all these areas is our result. </p>\n\n<p>Using dynamic programming, we can use the <code>h</code>, <code>l</code>, and <code>r</code> of each point in the previous row to compute the <code>h</code>, <code>l</code>, and <code>r</code> for every point in the next row in linear time.</p>\n\n<p><strong>Algorithm</strong></p>\n\n<p>Given row <code>matrix[i]</code>, we keep track of the <code>h</code>, <code>l</code>, and <code>r</code> of each point in the row by defining three arrays - <code>height</code>, <code>left</code>, and <code>right</code>.</p>\n\n<p><code>height[j]</code> will correspond to the height of <code>matrix[i][j]</code>, and so on and so forth with the other arrays.</p>\n\n<p>The question now becomes how to update each array.</p>\n\n<blockquote>\n  <p><code>height</code></p>\n</blockquote>\n\n<p><code>h</code> is defined as the number of continuous unfilled spaces in a line from our point. We increment if there is a new space, and set it to zero if the space is filled (we are using \'1\' to indicate an empty space and \'0\' as a filled one).</p>\n\n<pre><code>new_height[j] = old_height[j] + 1 if row[j] == \'1\' else 0\n</code></pre>\n\n<blockquote>\n  <p><code>left</code>:</p>\n</blockquote>\n\n<p>Consider what causes changes to the left bound of our rectangle. Since all instances of filled spaces occurring in the row above the current one have already been factored into the current version of <code>left</code>, the only thing that affects our <code>left</code> is if we encounter a filled space in our current row.</p>\n\n<p>As a result we can define:</p>\n\n<pre><code>new_left[j] = max(old_left[j], cur_left)\n</code></pre>\n\n<p><code>cur_left</code> is one greater than rightmost filled space we have encountered. When we "expand" the rectangle to the left, we know it can\'t expand past that point, otherwise it\'ll run into the filled space.</p>\n\n<blockquote>\n  <p><code>right</code>:</p>\n</blockquote>\n\n<p>Here we can reuse our reasoning in <code>left</code> and define:</p>\n\n<pre><code>new_right[j] = min(old_right[j], cur_right)\n</code></pre>\n\n<p><code>cur_right</code> is the leftmost occurrence of a filled space we have encountered.</p>\n\n<p><strong>Implementation</strong></p>\n\n<pre class="lang-py prettyprint-override"><code>def maximalRectangle(matrix):\n    if not matrix: return 0\n\n    m = len(matrix)\n    n = len(matrix[0])\n\n    left = [0] * n # initialize left as the leftmost boundary possible\n    right = [n] * n # initialize right as the rightmost boundary possible\n    height = [0] * n\n\n    maxarea = 0\n\n    for i in range(m):\n\n        cur_left, cur_right = 0, n\n        # update height\n        for j in range(n):\n            if matrix[i][j] == \'1\': height[j] += 1\n            else: height[j] = 0\n        # update left\n        for j in range(n):\n            if matrix[i][j] == \'1\': left[j] = max(left[j], cur_left)\n            else:\n                left[j] = 0\n                cur_left = j + 1\n        # update right\n        for j in range(n-1, -1, -1):\n            if matrix[i][j] == \'1\': right[j] = min(right[j], cur_right)\n            else:\n                right[j] = n\n                cur_right = j\n        # update the area\n        for j in range(n):\n            maxarea = max(maxarea, height[j] * (right[j] - left[j]))\n\n    return maxarea\n</code></pre>\n'}, {'answer_id': 64899570, 'author': 'emu', 'author_id': 797845, 'author_profile': 'https://Stackoverflow.com/users/797845', 'pm_score': 1, 'selected': False, 'text': '<p>Implementation of the stack-based algorithm in plain Javascript (with linear time complexity):</p>\n<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">\r\n<div class="snippet-code">\r\n<pre class="snippet-code-js lang-js prettyprint-override"><code>function maxRectangle(mask) {\n  var best = {area: 0}\n  const width = mask[0].length\n  const depth = Array(width).fill(0)\n  for (var y = 0; y &lt; mask.length; y++) {\n    const ranges = Array()\n    for (var x = 0; x &lt; width; x++) {\n      const d = depth[x] = mask[y][x] ? depth[x] + 1 : 0\n      if (!ranges.length || ranges[ranges.length - 1].height &lt; d) {\n        ranges.push({left: x, height: d})\n      } else {\n        for (var j = ranges.length - 1; j &gt;= 0 &amp;&amp; ranges[j].height &gt;= d; j--) {\n          const {left, height} = ranges[j]\n          const area = (x - left) * height\n          if (area &gt; best.area) {\n            best = {area, left, top: y + 1 - height, right: x, bottom: y + 1}\n          }\n        }\n        ranges.splice(j+2)\n        ranges[j+1].height = d\n      }\n    }\n  }\n  return best;\n}\n\nvar example = [\n[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],\n[1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0],\n[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],\n[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],\n[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],\n[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],\n[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],\n[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]\n\nconsole.log(maxRectangle(example))</code></pre>\r\n</div>\r\n</div>\r\n</p>\n'}]
['https://Stackoverflow.com/questions/7245', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/758/']