14

Given an NxNxN binary array (containing only 0's or 1's), how can we obtain the largest cuboid with a non-trivial solution i.e. in O(N^3) ?

--

It is the same problem that Find largest rectangle containing only zeros in an N×N binary matrix but in an upper dimension. Also, in my case, the largest rectangle can "cross the edge" of the array i.e. the space is like a torus for a 2D matrix.

For a 2D array, if the entry is :

00111
00111
11000
00000
00111

the solution depicted by 'X' is

00XXX
00XXX
11000
00000
00XXX

I've done the computation for a NxN binary array and find a solution for the largest rectangle problem in O(N^2) by following the idea in http://tech-queries.blogspot.de/2011/03/maximum-area-rectangle-in-histogram.html. But I don't know how to apply it for a 3D array.

--

Example for a 3x3x3 array where the solution "cross the edge":

111
100
011

111
001
111

011
110
011

the solution should be:

1XX
100
0XX

1XX
001
1XX

0XX
110
0XX
Community
  • 1
  • 1
badgvuria
  • 151
  • 4
  • Your question and its title confuse the use of the variable N. If you mean the size of one dimension of the array, you are probably seeking an O(N^3) algorithm rather than an O(N) one. Is there any reasonable limit on the value of N (in the sense of size of one dimension of the array) ? – High Performance Mark Mar 29 '12 at 10:35
  • 1
    In my opinion O(N^3) is impossible to achieve. If you are intresting in solution that runs in O(N^4) i can describe it. – Jarosław Gomułka Mar 29 '12 at 11:27
  • @HighPerformanceMark: Indeed, it is confusing, I've edited my post. I mean O(N^3). A reasonable limit is N=150. – badgvuria Mar 29 '12 at 11:51
  • @JarosławGomułka: Your solution is very welcome. But why do you think that it is impossible ? Also, an important constrain is the flexibility of the algorithm because I would like it works for a 4D array. At best, I would like to extend the current solution for 2D. – badgvuria Mar 29 '12 at 12:03

2 Answers2

5

This solution has O(N3 log2 N) complexity (may be optimized to O(N3 log N)). Additional integer array of size 2*8*N3 will be needed.

  1. Compute r(i,j,k): for each of the N2 rows, compute cumulative sum of all non-zero elements, resetting it when a zero element is found.
  2. Perform the following steps for various values of K, using Golden section search (or Fibonacci search) to find the maximum result.
  3. Compute c(i,j,k): for each of the N2 columns, compute cumulative sum of all elements with r(i,j,k) >= K, resetting it when an element with r(i,j,k) < K is found. For good visualization of steps 1 and 2, see this answer.
  4. Perform the last step for various values of M, using Golden section search to find the maximum result.
  5. Compute sum: for each of the N2 values of 3rd coordinate, compute cumulative sum of all elements with c(i,j,k) >= M, resetting it when an element with c(i,j,k) < M is found. Calculate sumKM and update the best so far result if necessary.

"cross the edge" property of the array is handled in obvious way: iterate every index twice and keep all cumulative sums not larger than N.

For multidimensional case, this algorithm has O(ND logD-1 N) time complexity and O(D*ND) space complexity.


Optimization to O(N3 log N)

Step 4 of the algorithm sets a global value for M. This step may be excluded (and complexity decreased by log N) if value for M is determined locally.

To do this, step 5 should be improved. It should maintain a double-ended queue (head of which contains local value of M) and a stack (keeping starting positions for all values of M, evicted from the queue).

While c(i,j,k) increases, it is appended to the tail of the queue.

If c(i,j,k) decreases, all larger values are removed from the queue's tail. If it decreases further (queue is empty), stack is used to restore 'sum' value and put corresponding 'M' value to the queue.

Then several elements may be removed from the head of the queue (and pushed to the stack) if this allows to increase local solution's value.

For multidimensional case, this optimization gives O(ND logD-2 N) complexity.

Community
  • 1
  • 1
Evgeny Kluev
  • 24,287
  • 7
  • 55
  • 98
  • What are rows and columns in this scenario exactly? Do you have a source for this algorithm that I could read or did you come up with this yourself? – Jan Schultke Feb 03 '20 at 12:09
  • Hi there! Thank you for your answer. I would very much like to understand this better. Is this an algorithm that you came up with or do you have a reference? Thanks again! – Michael Wehar Sep 29 '20 at 07:45
  • Did you mean to say that an approach like this only works for finding the largest cube? Or, am I mistaken? I can't get this to work for boxes. – Michael Wehar Sep 30 '20 at 08:57
  • I think that I get what you're doing now. Given numbers A and B. In O(N^3) time, for each cell (i, j, k) in the 3D array, you find the largest C such that there is an A by B by C box of 1's whose front bottom right corner is (i, j, k). – Michael Wehar Oct 14 '20 at 05:41
  • You then (somehow) search for the A and B combination that produces the largest boxes? I still don't quite get how you can do this with trying only log^2(N) many A and B combinations. – Michael Wehar Oct 14 '20 at 05:47
4

Here is only O(N^4).

Lets assume you are storing cubiod in bool cuboid[N][N][N];

bool array2d[N][N];

for(int x_min = 0; x_min < N; x_min++) {
   //initializing array2d
   for(int y = 0; y < N; y++) {
      for(int z = 0; z < N; z++) {
         array2d[y][z] = true;
      }
   }

   //computation
   for(int x_max = x_min; x_max < N; x_max++) {
      // now we want to find largest cube that
      // X coordinates are equal to x_min and x_max

      // cells at y,z can be used in cube if and only if
      // there are only 1's in cuboid[x][y][z] where x_min <= x <= x_max

      // so lets compute for each cell in array2d,
      // if are only 1's in cuboid[x][y][z] where x_min <= x <= x_max
      for(int y = 0; y < N; y++) {
         for(int z = 0; z < N; z++) {
            array2d[y][z] &= cubiod[x_max][y][z];
         }
      }

      //you already know how to find largest rectangle in 2d in O(N^2)
      local_volume = (x_max - x_min + 1) * find_largest_area(array2d);

      largest_volume = max(largest_volumne, local_volume);
   }
}

You can use the same trick, to compute best solution in X dimentions. Just reduce the problem to X-1 dimensions. Complexity: O(N^(2*X-2)).

Eric
  • 95,302
  • 53
  • 242
  • 374
Jarosław Gomułka
  • 4,935
  • 18
  • 24
  • 1
    `X coordinates are equal to x_min and x_max`, can't the X coordinates be somewhere between x_min and x_max? For example, suppose (x_min<)x1( – Priyank Bhatnagar Mar 29 '12 at 16:31
  • Keep in mind that this algorithm iterates over all combinations of (x_min, x_max). So it will also iterate over (x1+1, x_max) and (x_min, x1-1) and this cases aren't left out. – Jarosław Gomułka Mar 29 '12 at 16:40
  • Oh! I missed that statement. +1, neat solution. – Priyank Bhatnagar Mar 29 '12 at 16:47
  • Just out of curiosity, why is [this](http://ideone.com/rlEUr) solution wrong? I can't seem to find any test case. It extends the concept used for finding area in 2d array. – Priyank Bhatnagar Mar 29 '12 at 17:19
  • 1
    In your solution, array2d contains integers (maximal possible heights) while in mine, array2d contains booleans. This makes find2dArea much more complicated. I think this makes find2dArea necessary to search for largest cuboid:(. – Jarosław Gomułka Mar 29 '12 at 17:31
  • Yes! ( Note to reader :find2darea is `O(n^3)` in my link Using kadane's algorithm in 2d. ) – Priyank Bhatnagar Mar 29 '12 at 17:38