How can you find the max rectangular area in histogram recursively? - java

I need to come up with a recursive solution for the "Maximum rectangular area in a histogram" problem. For those not familiar with it, here´s an explanation:
A histogram is a display of statistical information that uses rectangles to show the frequency of data items. These rectangles are usually vertical.
In the histogram, all the bars are usually different sizes. In the problem, you have to find the maximum rectangular area in the histogram. For example, if the sizes are [4,1,4,5,6] the maximum area is 12 because we take the last 3 bars [4,5,6], take the shortest bar [4], and apply the rectangular area formula (4x3=12).
The only requirements are:
-It has to be done in java.
-Stacks can´t be used.
-It has to be recursive.
In case it helps, i have a non-recursive solution:
public static int MaxHistograma(int[] histograma) {
if (histograma.length == 1) {
return histograma[0];
}
int res = 0;
for (int i = 0; i < histograma.length - 1; i++) {
int min = histograma[i];
for (int j = i + 1; j < histograma.length; j++) {
min = Math.min(min, histograma[j]);
res = Math.max(histograma[j], Math.max(res, min * (j - i + 1)));
res = Math.max(res, histograma[i]);
}
}
return res;
}

If you start with the base case of a histogram with 1 column then the largest area is simply equal to height of the column.
When you add a include the 2nd column, the area may be either be
1) Equal to the max area from the previous histogram
2) Equal to the height of this 2nd column
3) Equal to the area of the new rectangle which has been formed horizontally
When you look at the third column, it's the same. It's either the max area from the previous histogram (2 cols), the height of the new column (red), or the area of the horizontal rectangle (purple).
Here is a code skeleton to achieve this
private int getLargestArea(int[] histogram)
{
if (histogram.length > 1)
{
int horizontalRectangleArea = 0; //TODO
int lastColumnHeight = 0; //TODO
return Math.max(
Math.max(horizontalRectangleArea, lastColumnHeight),
getLargestArea(Arrays.copyOf(histogram, histogram.length - 1)) //copy the array, subtracting 1 column
);
}
else
{
return histogram[0]; // height of single column
}
}

Related

Adjusting intensity on an image

I am trying to increase the intensity of a grayscale image while maintaining the outline of the image.The algorithm I'm creating only looks at values in the left, right, upper and lower neighbors of each cell, effectively only processing the interior cells of the array. Obviously there are lines and lines of code but I am being thrown the ArrayOutOfBoundsException on this one block (I can provide it all if needed). Can someone tell me what my problem is or offer advice on what needs a second look?
public Image getEdgeImage(){
Image edge = new Image(this);
for(int row = 1; row < numRows; row++) {
for(int col = 1 ; col < numColumns; col++) {
double Lx = -.5 * edge.pixels[row -1][col].getRed() + (.5 * edge.pixels[row + 1][col].getRed()) ;
double Ly = -.5 * edge.pixels[row][col -1].getRed() + (.5 * edge.pixels[row][col + 1].getRed());
int L = (int) Math.sqrt((Lx * Lx) + (Ly * Ly));
edge.pixels[row][col] = new Color(L, L, L);
}
}
return edge;
}
If your getting ArrayOutOfBoundException, Please do watch on the area your accessing the Array element by +/- the index.
In your program the line No 5 & 6, your accusing the next elements with out checking the array length.
edge.pixels[row + 1]
edge.pixels[row][col + 1]
Array Index will start from 0 to length-1, Suppose your array has the length of 10, and on the 9th iteration your program will check for the index 10 in line 5&6 the code highlighted above.

Scrolling through all color combinations on a vertical column of pixels

I'm trying to scroll through every single RGB color combination possible on a vertical set of pixels. In this example assume that the pixel column is 1080. I understand that all possible combinations amount to approximately 18 billion at that number. I can't seem to wrap my head around the loop structure. I have the loop for figuring all color combinations for one pixel here.
for(int r = 0;r < 256;r++){
for(int g = 0;g < 256;g++){
for(int b = 0;b < 256;b++){
pixelC =
Integer.toString(r)+":"+
Integer.toString(g)+":"+
Integer.toString(b)+";";
}
}
}
Now I need something that can apply the pixel color to the column. I'm just not sure how to work out the logic of doing this because I have to apply the color in all possible combinations. So having a vertical strip of all white with a vertical strip of all black is not my goal. Rather a sporadic peppering of pixels in all possible combinations.
What you are trying to accomplish is too difficult and cumbersome with for loops.
Basically, you are trying to count in base 256^3 = 16,777,216. And with a column height of 1080, the number of combinations is astronomical!
(256^3)^1080 ≈ 4.983 × 10^7802
Let me explain with a simplified example. Instead of a column height of 1080, let's say it is of height 4. And instead of having 16,777,216 different color combinations for each pixel, say we only have 10 different color combinations.
Furthermore, instead of color values being composed of RGB, let's say each color can have a value from 0-9. In this example, the column (of 4 pixels) can be in 10^4 = 10,000 different states.
Let's visualize this: Think about the column being on its side so it is horizontal and let's treat it like it's one of those combination locks with dials that can spin from 0-9.
This would be the initial state (All 4 dials/pixels at color = 0):
-------------------------
| 0 | 0 | 0 | 0 |
-------------------------
This would be the final state (All 4 dials/pixels at color = 9):
-------------------------
| 9 | 9 | 9 | 9 |
-------------------------
In your case, you would have a combination lock that has 1080 dials and each dial can spin from 0-16,777,215
Now, I was interested in how I can simplify the code so that you don't have to have 1080 for loops or n for loops in the general case where n is the height of the column.
Here's what I came up with:
// This represents the combination lock with 4 dials
int [] arr = new int [4];
// This represents how many states each dial can be in
int base = 10; // (0-9)
boolean done = false;
while (!done)
{
// just for printing out the current state of the array
System.out.println(Arrays.toString(arr));
int index = 0;
// get to the first dial that has not reached its max value
while (index < arr.length && arr[index] == base - 1)
{
index++;
}
// all dials are at the max value -> we are done
if (index == arr.length)
{
done = true;
}
else
{
// increase the first dial we found to not have a max value
arr[index]++;
// set all dials before it to 0
for (int i = 0; i < index; i++)
{
arr[i] = 0;
}
}
}
Note: This algorithm increases the values from left to right. I figured this made sense in adapting it to actual problem with a column in a graphic since you would start changing colors from the top down vs. bottom up. If you want colors to start changing from the bottom up, then it can easily be adapted by changing the indices, increments to decrements, etc.
Now, this example is for simple integer values and int arrays. How can we adapt it to your problem with colors?
First, let's assume that the column slice is an array of java.awt.Color
That is, int [] arr = new int [4]; becomes Color [] arr = new Color [4];
Next, instead of int base = 10; // (0-9) we would have int base = 16777216; // (0-16,777,215)
Now, the rest of the code is pretty much the same except we have to adapt a few things:
This:
while (index < arr.length && arr[index] == base - 1)
{
index++;
}
Needs to become this:
while (index < arr.length && arr[index].equals(Color.WHITE))
{
index++;
}
This:
// increase the first dial we found to not have a max value
arr[index]++;
Needs to become this:
// increase the first color we found to not have a max value
Color current = arr[index];
arr[index] = new Color(current.getRGB() + 1);
Lastly, for this portion:
// set all dials before it to 0
for (int i = 0; i < index; i++)
{
arr[i] = 0;
}
We can simply do:
// set all colors before it to 0
for (int i = 0; i < index; i++)
{
arr[i] = Color.BLACK;
}
Also, keep in mind you will need to initialize the Color array. This can be done like so:
for (int i = 0; i < arr.length; i++)
{
arr[i] = Color.BLACK;
}
I hope this helps. Good luck!

Trouble finding path in a grid

I am trying to find number of paths between top left and bottom right cells on a checker board. i can only move to the adjacent right and adjacent bottom cell. This way i can have a maximum of 2 non intersecting simple paths. I am using a recursive approach.
private void processMatrix()
{
if(matrix[0][0]!=1 || matrix[0][0]!=matrix[ROWS-1][COLUMNS-1])
System.out.println("No Path Exists between bottom right and top left cells");
int row=0;
int col=0;
traverse(row,col);
}
private boolean traverse(int row, int col)
{
path.add(new Point(row,col));
if(row+1<ROWS)
{
if(matrix[row+1][col]==0)
{
return false;
}
if(matrix[row+1][col]==1)
{
traverse(row+1,col);
}
}
if(col+1<COLUMNS)
{
if(matrix[row][col+1]==0)
{
return false;
}
if(matrix[row][col+1]==1)
{
traverse(row,col+1);
}
}
if(col==COLUMNS-1 && row==ROWS-1)
return true;
return false;
}
But with this code i am only able to traverse the lower triangular matrix. And when i reverse the order of if blocks in the traverse() function i am only able to traverse a path in the upper triangular matrix. Unable to figure out what is wrong. I also want to detect intersecting paths. Please help.
EDIT:
The matrix consists of 0s and 1s.
A path exists if it is connected by adjacent cells containing only 1s. In other words the path will be a chain of 1s.
You seem to be overcomplicating things with your code. If your matrix is 0s and 1s, use boolean instead of int. Non-intersecting paths seems a bit silly, since all paths are equally valid in taxicab geometry. Here's the simple solution for finding the number all paths, it will show you how it works with the block of system.out prints:
int rows = 9;
int columns = 8;
boolean[][] matrix = new boolean[rows][columns];
for (boolean[] arr : matrix) {/* Set values of matrix such that true = can pass thru that space, false = space blocked */
Arrays.fill(arr, true);
}
matrix[4][6] = false;
matrix[2][5] = false;
int[][] paths = new int[rows][columns];//number of paths reaching each space in i steps
paths[0][0] = 1; //Starting space
for (int i = 0; i < rows + columns - 2; i++) {//Taxicab distance is always x+y, i = distance travelled so far
int[][] newPaths = new int[rows][columns]; //number of paths reaching each space in i+1 steps
for (int x = i >= columns ? i - columns + 1 : 0; x <= i && x < rows;) { //x is traditionally columns but it doesn't matter
int y = i - x; //if statement is x declaration ensures that this is < columns
int newX = x + 1; //will be used repeatedly
int newY = y + 1; //will be used repeatedly
if (newX < rows && matrix[newX][y]) newPaths[newX][y] += paths[x][y];
if (newY < columns && matrix[x][newY]) newPaths[x][newY] += paths[x][y];
x = newX;
}
paths = newPaths;
for (int x = 0; x < rows; x++) { //optional, show the algorithm at work
for (int y = 0; y < columns; y++) {
int r = paths[x][y];
System.out.print(r);
if (r < 100) System.out.print(" ");
if (r < 10) System.out.print(" ");
}
System.out.println();
}
System.out.println();
}
System.out.println(paths[rows - 1][columns - 1]); //result
If all you want to determine is whether a path exists, replace int[][] paths with boolean[][] paths and change the operations accordingly.
This is a fundamental dynamic programming problem.
Let dp[R][C] be the number of paths from the top-left cell to the cell on row R and column C (1-indexed).
Initial values (when R or C is 1):
dp[R][1] = 1 if matrix[i][1] has value 1 for i = 1..R, otherwise dp[R][1] = 0.
dp[1][C] = 1 if matrix[1][j] has value 1 for j = 1..C, otherwise dp[1][C] = 0.
Then dp[R][C] = dp[R-1][C] + dp[R][C-1] if matrix[R][C] = 1, otherwise dp[R][C] = 0 (for R, C >= 2)
And this is it. The intuition behind this idea is that if we know that we can get to cell on row R-1, column C by N different roads, then if we go down once, we will get N different roads to cell [R, C]. Analogically for going right from cell [R, C-1] to [R, C].
Finally, the answer is in dp[N][M], where N and M are the dimensions of the matrix.

Finding the average value of the color red in a BufferedImage (Java)

I want find the average red RGB-value of a MyImage (extending BufferedImage). I save the red value for each pixel in the image to an array red[]. At the end I want to sum these ut to find the average value of red. But when I run this code on a MyImage it only prints 0. How can i get this method to work properly? (The code not included here works just fine)
public class MyImage extends BufferedImage {
public MyImage(int width, int height, int imageType) {
super(width, height, imageType);
}
public void findAverageRedValue(){
int height = this.getHeight();
int width = this.getWidth();
int[] red = new int[height*width];
Map m = new HashMap();
for(int i=0; i < width ; i++)
{
for(int j=0; j < height ; j++)
{
ColorModel colorModel = this.getColorModel();
int rCol = colorModel.getRed(j*i);
red[red.length - 1] = rCol;
}
}
int sum = 0;
for(int i = 0; i < red.length; i++)
sum += red[i];
int averageRed = sum/red.length;
System.out.println(averageRed);
}
}
You're assigning elements of your array as:
red[red.length - 1] = rCol;
This will, in every possible situation, only assign the last element of the array. The length property of an array isn't like the size() of a collection; it's a static value which is based on the initialised dimension of the array.
So all but one of the array entries will be zero. Thus at the end, the sum will be between 0 and 255 - and when divided by a (likely) larger number, this comes out as zero. (There's a possible issue here in that you're doing integer division, but this is perhaps not critical).
To fix this, you'll need to change which array index you assign to. You could either keep a separate counter for the array index - or, make use of the existing i and j to do:
red[i * width + j] = rCol;
Either way, this will put each pixel's red component into a separate array location, and thus enable you to sum them correctly.
Integer division is a potential gotcha in Java, and that's what you're doing here at the end. It may be better to get the fractional average via sum / (float)red.length, though as long as you know what's happening and you're happy to have truncation to the nearest integer, this may not be necessary.

get original index of a sorted array in java(Android)

In my code, i got a List of elements to loop through and calculate some values, now:
double targetRatio = Math.min((double)w/h, (double)h/w);//height & width of the screen
List<Size> sizes //populated with supported height and width
double ratioArray[];
int i;
for (i = 0; i <= sizes.size(); i++)
{
double ratio = Math.min((double)sizes.get(i).width/sizes.get(i).height, (double)sizes.get(i).height/sizes.get(i).width);
ratioArray[i] = Math.abs(ratio - targetRatio);
// Math.min((double)sizes.get(i).width/w, (double)w/sizes.get(i).width);
// Math.min((double)h/sizes.get(i).height, (double)sizes.get(i).height/h);
//sizes.get(i).width
//sizes.get(i).height
}
the lower the value in ratioArray[i] the better ratio i got;now i am stuck at locating the best ratio, i can do this:
Arrays.sort(ratioArray);
but then how do i get the index back? i have to make the min value point to it's size
Best way is to iterate through ratioArray and DO NOT use Arrays.sort(ratioArray);
double targetRatio = Math.min((double)w/h, (double)h/w);//height & width of the screen
List<Size> sizes //populated with supported height and width
double ratioArray[];
int i;
for (i = 0; i <= sizes.size(); i++)
{
double ratio = Math.min((double)sizes.get(i).width/sizes.get(i).height, (double)sizes.get(i).height/sizes.get(i).width);
ratioArray[i] = Math.abs(ratio - targetRatio);
// Math.min((double)sizes.get(i).width/w, (double)w/sizes.get(i).width);
// Math.min((double)h/sizes.get(i).height, (double)sizes.get(i).height/h);
//sizes.get(i).width
//sizes.get(i).height
}
After the above code put this,
int min = ratioArray[0];
int minindex;
for (int i = 0; i < ratioArray.length; i++) {
if(min > ratioArray[i]) {
min = ratioArray[i];
minindex = i;
}
}
And you will get your minindex
Is there a need to compute all ratios first and then sort them?
I would compute the ratio in the for loop (as you do it now) and then check, if it is better than the best computed ratio till now. If yes, store it (and its index) as bestRatio and bestRatioIndex and go on - if not, just go for the next loop.
After the loop, you have the best ratio and its index in the two variables.
You could even leave the loop then in-between, if you find an exact matching.

Categories