Floyd's algorithm - algorithm

This I keep running but its not running correctly I am not getting the right answers
public static void Floyd(int n, int [][] W, int [][] D, int [][] P)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
P[i][j]=0;
D = W;
for (int k = 0; k<=n; k++)
for(int i = 0; i<=n; i++)
for(int j=1;j<=n;j++)
{
if (D[i][k] + D[k][j]< D[i][j])
{
P[i][j] =k;
D[i][j] = D[i][k]+D[k][j];
}
}
} // end Floyd
public static void printArray(int n, int [][] A) {
int i, j;
System.out.println();
System.out.print(" ");
for (i = 1; i <= n; i++)
System.out.printf("%7d", i);
System.out.println("\n");
for (i = 1; i <= n; i++) {
System.out.printf("%7d", i);
for (j = 1; j <= n; j++)
System.out.printf("%7d", A[i][j]);
System.out.println();
}
System.out.println();
} // end printArray
Here is my main which and the above are my print method and floyd methods... I think there is something wrong with the floyd method
public static void main(String[] args) throws IOException {
Scanner kbd = new Scanner(System.in);
Scanner input;
String inputFileName;
System.out.print("\nEnter input file name: ");
inputFileName = kbd.nextLine();
FileReader f = new FileReader(inputFileName);
input = new Scanner(f);
int i, j, n;
n = input.nextInt();
System.out.println();
int [][] W = new int[n+1][n+1];
int [][] D = new int[n+1][n+1];
int [][] P = new int[n+1][n+1];
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
W[i][j] = input.nextInt();
System.out.println("W is: ");
printArray(n, W);
Floyd(n, W, D, P);
System.out.println("D is: ");
printArray(n, D);
System.out.println("P is: ");
printArray(n, P);
Here is the output i am getting The graphs are not filling the way that they are supposed too
W is:
1 2 3 4 5
1 0 10 9999 10 50
2 90 0 30 20 9999
3 9999 9999 0 40 9999
4 9999 9999 20 0 30
5 30 9999 9999 90 0
D is:
1 2 3 4 5
1 0 0 0 0 0
2 0 0 0 0 0
3 0 0 0 0 0
4 0 0 0 0 0
5 0 0 0 0 0
P is:
1 2 3 4 5
1 0 0 0 0 0
2 0 0 0 0 0
3 0 0 0 0 0
4 0 0 0 0 0
5 0 0 0 0 0

Related

What is wrong with the solution to this problem

I am trying to solve:
https://www.spoj.com/problems/ANARC05B/
I am using Binary Search to solve this problem.
I think I have followed the correct approach.
Can anybody help me with a test case that would fail?
Below is my code, it passes on the sample test cases, i dont see a problem with my code but still not sure why i get WA!! Please help!!
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int BinarySearch(vector<int> arr, int key)
{
int minNum = 0;
int maxNum = arr.size() - 1;
while (minNum <= maxNum)
{
int mid = (minNum + maxNum) / 2;
if (key == arr[mid])
{
return mid;
}
else if (key < arr[mid])
{
maxNum = mid - 1;
}
else
{
minNum = mid + 1;
}
}
return -1;
}
signed long Solve(vector<int> First, vector<int> Second)
{
// Find the intersections in both the arrays and store the indices for them.
vector<int> FirstInterIndices;
vector<int> SecondInterIndices;
for (int i = 0; i < Second.size(); i++)
{
int idx = BinarySearch(First, Second[i]);
if (idx != -1)
{
SecondInterIndices.push_back(i);
FirstInterIndices.push_back(idx);
}
}
if (FirstInterIndices.empty())
{
FirstInterIndices.push_back(FirstInterIndices.size() - 1);
SecondInterIndices.push_back(SecondInterIndices.size() - 1);
}
//Find Intersections ends
//Calc the sum upto intersections in both the arrays and store them
vector<signed long> FirstInterSum;
vector<signed long> SecondInterSum;
for (int i = 0; i < SecondInterIndices.size(); i++)
{
int k = 0;
signed long Sum = 0;
if (i > 0)
{
k = SecondInterIndices[i - 1] + 1;
}
for (; k <= SecondInterIndices[i]; k++)
{
Sum += (signed long)Second[k];
}
SecondInterSum.push_back(Sum);
}
signed long SumLeft = 0;
if (SecondInterIndices.size() > 0)
{
for (int k = SecondInterIndices[SecondInterIndices.size() - 1] + 1; k < Second.size(); k++)
{
SumLeft += (signed long)Second[k];
}
SecondInterSum.push_back(SumLeft);
}
for (int i = 0; i < FirstInterIndices.size(); i++)
{
int k = 0;
signed long Sum = 0;
if (i > 0)
{
k = FirstInterIndices[i - 1] + 1;
}
for (; k <= FirstInterIndices[i]; k++)
{
Sum += (signed long)First[k];
}
FirstInterSum.push_back(Sum);
}
if (FirstInterIndices.size() > 0)
{
SumLeft = 0;
for (int k = FirstInterIndices[FirstInterIndices.size() - 1] + 1; k < First.size(); k++)
{
SumLeft += (signed long)First[k];
}
FirstInterSum.push_back(SumLeft);
}
// Calc sum upto intersections ENDs
// Compare corresponding elements (sum upto intersections) and add the max from First and Second
signed long MaxSum = 0;
int j = 0;
for (; j < FirstInterSum.size(); j++)
{
if (j < SecondInterSum.size())
{
if (FirstInterSum[j] > SecondInterSum[j])
{
MaxSum += FirstInterSum[j];
}
else
{
MaxSum += SecondInterSum[j];
}
}
}
// If Any sum exists after last intersection add that as well.
if (j < FirstInterSum.size())
{
MaxSum += FirstInterSum[FirstInterSum.size() - 1];
}
if (j < SecondInterSum.size())
{
MaxSum += SecondInterSum[SecondInterSum.size() - 1];
}
return MaxSum;
}
vector<int> getArray()
{
vector<int> res;
int n;
cin >> n;
int x;
for (int i = 0; i < n; i++)
{
cin >> x;
res.push_back(x);
}
return res;
}
int main()
{
for (;;)
{
vector<int> First = getArray();
if (First.size() == 0)
return 0;
vector<int> Second = getArray();
cout << Solve(First, Second);
}
return 0;
}
You get WA because the output format is incorrect. I ran your code, and the output looks like this:
13 3 5 7 9 20 25 30 40 55 56 57 60 62
11 1 4 7 11 14 25 44 47 55 57 100
4 -5 100 1000 1005
3 -12 1000 1001
0450
2100
Program ended with exit code: 0
but the expected format should be:
13 3 5 7 9 20 25 30 40 55 56 57 60 62
11 1 4 7 11 14 25 44 47 55 57 100
4 -5 100 1000 1005
3 -12 1000 1001
0
450
2100
Program ended with exit code: 0
difference is 0 and 450 are not on the same line.
But this problem does not require neither binary search nor dynamic programming (as it is marked at the site) and might be solved in linear time (the best possible)
Make two indices - for the first array and for the second one.
At every step move index that refers to smaller element (like in merge procedure of merge sort). When moving, calculate current sum (sum between intersection points).
When both indices point to equal values, you have found intersection point. Choose larger current sum from both arrays, add it and intersection item to result, reset sums to zero.
Pseudocode sketch
if a[ia] < b[ib])
asum += a[ia++]
else
if a[ia] > b[ib])
bsum += b[ib++]
else
result += max(asum, bsum) + a[ia]
asum = bsum = 0
ia++
ib++

Longest Common Subsequence taking maximum of all the three possible cases

I approached the Longest Common Subsequence as:
LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) );
Whereas the texts show the logic for the problem to be like:
if( String1[m]==String2[n] )
LCS(m,n) = LCS(m-1,n-1) + 1;
else LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1) );
Will my approach produce incorrect results? if yes, then in what kind of a situation? If it is correct, how do you justify the correctness?
Thanks in advance!
My (badly) Java version, it runs correctly?
//'main' method must be in a class 'Rextester'.
//Compiler version 1.8.0_111
import java.util.*;
import java.lang.*;
class Rextester
{
public static void main(String args[])
{
int[] a = {1,1,1,1,2,3,2,3};
int[] b = {1,1,1,1,3,4,3,4};
System.out.println(solve(a, b).toString());
System.out.println(solve2(a, b).toString());
}
private static void printL(int[][]len, int m, int n, int[] a, int[] b)
{
System.out.print(" a→ ");
for (int j = 0; j < m; ++j)
{
System.out.print(a[j]);
System.out.print(" ");
}
System.out.println();
for (int i = 0; i <= n; ++i)
{
if (i > 0) { System.out.print(" "); System.out.print(b[i-1]); System.out.print(" "); }
else { System.out.print("b↓ "); }
for (int j = 0; j <= m; ++j)
{
System.out.print(len[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
private static List<Integer> solve(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 1");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = a[j] == b[i] ? 1 + len[i][j] : Math.max(len[i+1][j], len[i][j+1]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
private static List<Integer> solve2(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 2");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = Math.max(Math.max(len[i+1][j], len[i][j+1]), (a[j] == b[i] ? 1 : 0) + len[i][j]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
}
output on rextester:
Method 1
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]
Method 2
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]
My sketchy proof:
If you look at any row LCS(m) in the table above, you'll see that they all have increasing values, or they're all monotonically increasing. They cannot be decreasing since LCS(m,n) means longest common subsequence of (sub)string1 of length m and (sub)string2 of length n, if n2 >= n1 then LCS(m,n2) >= LCS(m,n1) because if n2 >= n1, LCS(m,n2) contains LCS(m,n1).
For the column LCS(n) you use the same proof. Now you have LCS(m,n) <= LCS(m,n+1) and LCS(m,n) <= LCS(m+1,n), which means your taking maximum of all three possible cases are correct.
LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) );
takes the wrong path only when String1[m] != String2[n] and (LCS(m-1,n-1) > LCS(m,n-1) or LCS(m-1,n-1) > LCS(m-1,n)), but the latter case (LCS(m-1,n-1) > LCS(m,n-1) or LCS(m-1,n-1) > LCS(m-1,n)) never happens. So your approach is correct.

Can separate, forked, processes jointly access shared dynamically allocated, pointer, memory?

I am trying to parallelize the addition of two simple 4x4 matrices. The child process adds only odd rows and the parents adds even ones. However, I can't seem to get the processes to work on shared pointer memory and the output is always given in halves, shown beneath the code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
int A[4][4] = {{1,2,3,4},{6,7,8,9},{11,12,13,14},{16,17,18,19}};
int B[4][4] = {{1,2,3,4},{6,7,8,9},{11,12,13,14},{16,17,18,19}};
int** C = (int**)malloc(sizeof(int)*4);
for (int z = 0; z<4; z++) {
C[z] = (int*)malloc(sizeof(int)*4);
}
pid_t cp;
printf("Before fork\n");
cp = fork();
if (cp == 0) {
for(int i = 1; i < 4; i+=2) {
for(int j = 0; j < 4; j++) {
printf("child process\n");
printf("We are adding cell %d,%d\n",i,j);
C[i][j] = A[i][j] + B[i][j];
sleep(1);
}
}
} else {
for (int k = 0; k < 4; k+=2) {
for(int l = 0; l < 4; l++) {
printf("parent process\n");
printf("We are adding cell %d,%d\n",k,l);
C[k][l] = A[k][l] + B[k][l];
sleep(1);
}
}
}
sleep(10);
printf("We are printing C here\n");
for (int m = 0; m < 4; m++) {
for(int n = 0; n < 4; n++) {
printf("%d ",C[m][n]);
}
printf("\n");
}
}
This is the output of the final for loop in the above code:
We are printing C here
0 0 0 0
12 14 16 18
0 0 0 0
32 34 36 38
We are printing C here
2 4 6 8
0 0 0 0
22 24 26 28
0 0 0 0

Adressing for-loops in big O notation

I have the Following Loops:
n = 2^M
for(int i = n; i > 0; i--){
for(int j = 1; j < n ; j*=2){
for(int k = 0 ; k < j ; k++){
}
}
}
Im trying to understnad how to approach this, i have tried to break it down to single steps but with no luck. if someone can explane me how to look at this and what to look for in this type of question.
why don't you just instrument it, to see what happens?
for example
public static void main(String[] args) {
int[] bb = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //try other values here like 1,10,100
for (int b : bb) {
int n = (int) Math.pow(2, b);
int l1 = 0;
int l2 = 0;
int l3 = 0;
for (int i = n; i > 0; i--) {
l1++;
for (int j = 1; j < n; j *= 2) {
l2++;
for (int k = 0; k < j; k++) {
l3++;
}
}
}
System.out.println(b+" "+l1+" "+l2+" "+l3);
}
}
you'd have something like
1 2 2 2
2 4 8 12
3 8 24 56
4 16 64 240
5 32 160 992
6 64 384 4032
7 128 896 16256
8 256 2048 65280
9 512 4608 261632
10 1024 10240 1047552
what does it seem?

Puzzle: Find largest rectangle (maximal rectangle problem)

What's the most efficient algorithm to find the rectangle with the largest area which will fit in the empty space?
Let's say the screen looks like this ('#' represents filled area):
....................
..............######
##..................
.................###
.................###
#####...............
#####...............
#####...............
A probable solution is:
....................
..............######
##...++++++++++++...
.....++++++++++++###
.....++++++++++++###
#####++++++++++++...
#####++++++++++++...
#####++++++++++++...
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?
Shog9 wrote:
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)?
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?
I'm the author of that Dr. Dobb's article and get occasionally asked about an implementation. Here is a simple one in C:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int one;
int two;
} Pair;
Pair best_ll = { 0, 0 };
Pair best_ur = { -1, -1 };
int best_area = 0;
int *c; /* Cache */
Pair *s; /* Stack */
int top = 0; /* Top of stack */
void push(int a, int b) {
s[top].one = a;
s[top].two = b;
++top;
}
void pop(int *a, int *b) {
--top;
*a = s[top].one;
*b = s[top].two;
}
int M, N; /* Dimension of input; M is length of a row. */
void update_cache() {
int m;
char b;
for (m = 0; m!=M; ++m) {
scanf(" %c", &b);
fprintf(stderr, " %c", b);
if (b=='0') {
c[m] = 0;
} else { ++c[m]; }
}
fprintf(stderr, "\n");
}
int main() {
int m, n;
scanf("%d %d", &M, &N);
fprintf(stderr, "Reading %dx%d array (1 row == %d elements)\n", M, N, M);
c = (int*)malloc((M+1)*sizeof(int));
s = (Pair*)malloc((M+1)*sizeof(Pair));
for (m = 0; m!=M+1; ++m) { c[m] = s[m].one = s[m].two = 0; }
/* Main algorithm: */
for (n = 0; n!=N; ++n) {
int open_width = 0;
update_cache();
for (m = 0; m!=M+1; ++m) {
if (c[m]>open_width) { /* Open new rectangle? */
push(m, open_width);
open_width = c[m];
} else /* "else" optional here */
if (c[m]<open_width) { /* Close rectangle(s)? */
int m0, w0, area;
do {
pop(&m0, &w0);
area = open_width*(m-m0);
if (area>best_area) {
best_area = area;
best_ll.one = m0; best_ll.two = n;
best_ur.one = m-1; best_ur.two = n-open_width+1;
}
open_width = w0;
} while (c[m]<open_width);
open_width = c[m];
if (open_width!=0) {
push(m0, w0);
}
}
}
}
fprintf(stderr, "The maximal rectangle has area %d.\n", best_area);
fprintf(stderr, "Location: [col=%d, row=%d] to [col=%d, row=%d]\n",
best_ll.one+1, best_ll.two+1, best_ur.one+1, best_ur.two+1);
return 0;
}
It takes its input from the console. You could e.g. pipe this file to it:
16 12
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 1 1 0 0 1 0 0 0 1 1 0 1 0
0 0 0 1 1 0 1 1 1 0 1 1 1 0 1 0
0 0 0 0 1 1 * * * * * * 0 0 1 0
0 0 0 0 0 0 * * * * * * 0 0 1 0
0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0
0 0 1 0 0 0 0 1 0 0 1 1 1 0 1 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0
And after printing its input, it will output:
The maximal rectangle has area 12.
Location: [col=7, row=6] to [col=12, row=5]
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.
#lassevk
I found the referenced article, from DDJ: The Maximal Rectangle Problem
I am the author of the Maximal Rectangle Solution on LeetCode, which is what this answer is based on.
Since the stack-based solution has already been discussed in the other answers, I would like to present an optimal O(NM) dynamic programming solution which originates from user morrischen2008.
Intuition
Imagine an algorithm where for each point we computed a rectangle by doing the following:
Finding the maximum height of the rectangle by iterating upwards until a filled area is reached
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
For example finding the rectangle defined by the yellow point:
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 height above that point).
For each point we define some variables:
h - the height of the rectangle defined by that point
l - the left bound of the rectangle defined by that point
r - the right bound of the rectangle defined by that point
These three variables uniquely define the rectangle at that point. We can compute the area of this rectangle with h * (r - l). The global maximum of all these areas is our result.
Using dynamic programming, we can use the h, l, and r of each point in the previous row to compute the h, l, and r for every point in the next row in linear time.
Algorithm
Given row matrix[i], we keep track of the h, l, and r of each point in the row by defining three arrays - height, left, and right.
height[j] will correspond to the height of matrix[i][j], and so on and so forth with the other arrays.
The question now becomes how to update each array.
height
h 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).
new_height[j] = old_height[j] + 1 if row[j] == '1' else 0
left:
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 left, the only thing that affects our left is if we encounter a filled space in our current row.
As a result we can define:
new_left[j] = max(old_left[j], cur_left)
cur_left 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.
right:
Here we can reuse our reasoning in left and define:
new_right[j] = min(old_right[j], cur_right)
cur_right is the leftmost occurrence of a filled space we have encountered.
Implementation
def maximalRectangle(matrix):
if not matrix: return 0
m = len(matrix)
n = len(matrix[0])
left = [0] * n # initialize left as the leftmost boundary possible
right = [n] * n # initialize right as the rightmost boundary possible
height = [0] * n
maxarea = 0
for i in range(m):
cur_left, cur_right = 0, n
# update height
for j in range(n):
if matrix[i][j] == '1': height[j] += 1
else: height[j] = 0
# update left
for j in range(n):
if matrix[i][j] == '1': left[j] = max(left[j], cur_left)
else:
left[j] = 0
cur_left = j + 1
# update right
for j in range(n-1, -1, -1):
if matrix[i][j] == '1': right[j] = min(right[j], cur_right)
else:
right[j] = n
cur_right = j
# update the area
for j in range(n):
maxarea = max(maxarea, height[j] * (right[j] - left[j]))
return maxarea
I implemented the solution of Dobbs in Java.
No warranty for anything.
package com.test;
import java.util.Stack;
public class Test {
public static void main(String[] args) {
boolean[][] test2 = new boolean[][] { new boolean[] { false, true, true, false },
new boolean[] { false, true, true, false }, new boolean[] { false, true, true, false },
new boolean[] { false, true, false, false } };
solution(test2);
}
private static class Point {
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x;
public int y;
}
public static int[] updateCache(int[] cache, boolean[] matrixRow, int MaxX) {
for (int m = 0; m < MaxX; m++) {
if (!matrixRow[m]) {
cache[m] = 0;
} else {
cache[m]++;
}
}
return cache;
}
public static void solution(boolean[][] matrix) {
Point best_ll = new Point(0, 0);
Point best_ur = new Point(-1, -1);
int best_area = 0;
final int MaxX = matrix[0].length;
final int MaxY = matrix.length;
Stack<Point> stack = new Stack<Point>();
int[] cache = new int[MaxX + 1];
for (int m = 0; m != MaxX + 1; m++) {
cache[m] = 0;
}
for (int n = 0; n != MaxY; n++) {
int openWidth = 0;
cache = updateCache(cache, matrix[n], MaxX);
for (int m = 0; m != MaxX + 1; m++) {
if (cache[m] > openWidth) {
stack.push(new Point(m, openWidth));
openWidth = cache[m];
} else if (cache[m] < openWidth) {
int area;
Point p;
do {
p = stack.pop();
area = openWidth * (m - p.x);
if (area > best_area) {
best_area = area;
best_ll.x = p.x;
best_ll.y = n;
best_ur.x = m - 1;
best_ur.y = n - openWidth + 1;
}
openWidth = p.y;
} while (cache[m] < openWidth);
openWidth = cache[m];
if (openWidth != 0) {
stack.push(p);
}
}
}
}
System.out.printf("The maximal rectangle has area %d.\n", best_area);
System.out.printf("Location: [col=%d, row=%d] to [col=%d, row=%d]\n", best_ll.x + 1, best_ll.y + 1,
best_ur.x + 1, best_ur.y + 1);
}
}
#lassevk
// 4. Outer double-for-loop to consider all possible positions
// for topleft corner.
for (int i=0; i < M; i++) {
for (int j=0; j < N; j++) {
// 2.1 With (i,j) as topleft, consider all possible bottom-right corners.
for (int a=i; a < M; a++) {
for (int b=j; b < N; b++) {
HAHA... O(m2 n2).. That's probably what I would have come up with.
I see they go on to develop optmizations... looks good, I'll have a read.
Implementation of the stack-based algorithm in plain Javascript (with linear time complexity):
function maxRectangle(mask) {
var best = {area: 0}
const width = mask[0].length
const depth = Array(width).fill(0)
for (var y = 0; y < mask.length; y++) {
const ranges = Array()
for (var x = 0; x < width; x++) {
const d = depth[x] = mask[y][x] ? depth[x] + 1 : 0
if (!ranges.length || ranges[ranges.length - 1].height < d) {
ranges.push({left: x, height: d})
} else {
for (var j = ranges.length - 1; j >= 0 && ranges[j].height >= d; j--) {
const {left, height} = ranges[j]
const area = (x - left) * height
if (area > best.area) {
best = {area, left, top: y + 1 - height, right: x, bottom: y + 1}
}
}
ranges.splice(j+2)
ranges[j+1].height = d
}
}
}
return best;
}
var example = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0],
[0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
console.log(maxRectangle(example))

Resources