algorithm for largest island in a given matrix - java

Given a 2 X 2 matrix, return different island sizes that is possible
For example, the following matrix should return [5, 7].
1 0 0 0 1
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
This is fairly straightforward problem. I am using a boolean visited matrix of same size and traverse the matrix in DFS fashion. I have implemented it here. for some reason, I am getting output as [1]. I tried debugging but my mind stopped working now. I am missing something silly I believe.
public class IslandConnectedCell {
public static void main(String[] args) {
int[][] input = {
{1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1}
};
dfsIsland(input);
}
public static void dfsIsland(int[][] input) {
int rows = input.length;
int cols = input[0].length;
List<Integer> countList = new ArrayList<>();
boolean visited[][] = new boolean[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; cols++) {
if (input[row][col] == 1 && !visited[row][col]) {
int count = mark(row, col, input, visited, rows, cols, 0);
countList.add(count);
}
}
}
System.out.println(countList);
}
public static int mark(int row, int col, int[][] input, boolean[][] visited, int rows, int cols, int count) {
if (row >= rows || row < 0 || col >= cols || col < 0) {
return 0;
}
if (input[row][col] == 0 || visited[row][col]) {
return 0;
}
visited[row][col] = true;
count+=1;
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
if (i != row || j != col) {
mark(i, j, input, visited, rows, cols, count);
}
}
}
return count;
}
}

There are two errors in your code.
See comment by Mick for first error:
One obvious problem in dfsIsland() is at least that for (int col = 0; col < cols; cols++) should probably be for (int col = 0; col < cols; col++) instead (maybe even better to use the common i and j for the row/col indices).
Second error is your use of count in the mark method, most glaringly the lack of using the return value in the recursive call. Remember, Java is pass-by-value.
Hint: I suggest you remove count as a parameter.
Once you fix the errors, output will be:
[7, 2, 2]
public class IslandConnectedCell {
public static void main(String... args) {
int[][] board = { {1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1} };
System.out.println(new IslandConnectedCell(board).getIslandSizes());
}
private final int[][] board;
private final int rows;
private final int cols;
public IslandConnectedCell(int[][] board) {
this.board = board;
this.rows = board.length;
this.cols = board[0].length;
}
public List<Integer> getIslandSizes() {
boolean visited[][] = new boolean[this.rows][this.cols];
List<Integer> countList = new ArrayList<>();
for (int row = 0; row < this.rows; row++)
for (int col = 0; col < this.cols; col++)
if (this.board[row][col] == 1 && ! visited[row][col])
countList.add(mark(row, col, visited));
return countList;
}
private int mark(int row, int col, boolean[][] visited) {
if (row >= this.rows || row < 0 || col >= this.cols || col < 0 || this.board[row][col] == 0 || visited[row][col])
return 0;
visited[row][col] = true;
int count = 1;
for (int r = -1; r <= 1; r++)
for (int c = -1; c <= 1; c++)
if (r != 0 || c != 0)
count += mark(row + r, col + c, visited);
return count;
}
}
UPDATE
To get the desired output of [7, 4] (original question), the board would need to use horizontal wraparound, so the two small islands on the bottom line becomes a single larger island.
That is easily accomplished by modifying one line of code to wraparound the column index using the % modulus operator:
count += mark(row + r, (col + c + this.cols) % this.cols, visited);

Related

Given a matrix find all adjacent same elements

I have a 2D matrix, now I want to pick an element e and see all adjacent elements (i+1,j), (i-1,j) , (i,j+1), (i,j-1) and navigate if they are same as e and count how many are matching like that. Now find the maximum count that is possible.
example:
1 2 3 4
1 2 4 4
4 2 4 5
6 9 4 7
Output: 5.
as 4 is the element that repeats 5 times and all are adjacents, whereas 1 appears only 2 times and 2 appears only 3 times.
How to solve this program? I tried with BFS but got stuck on how to maintain the count here?
static class pair {
int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
static int ROW = 4;
static int COL = 4;
// Direction vectors
static int dRow[] = { -1, 0, 1, 0 };
static int dCol[] = { 0, 1, 0, -1 };
// Function to check if a cell
// is be visited or not
static boolean isValid(boolean vis[][], int row, int col) {
// If cell lies out of bounds
if (row < 0 || col < 0 || row >= ROW || col >= COL)
return false;
// If cell is already visited
if (vis[row][col])
return false;
// Otherwise
return true;
}
static void BFS(int grid[][], boolean vis[][], int row, int col) {
// Stores indices of the matrix cells
Queue<pair> q = new LinkedList<>();
// Mark the starting cell as visited
// and push it into the queue
q.add(new pair(row, col));
vis[row][col] = true;
// Iterate while the queue
// is not empty
int max = 0;
while (!q.isEmpty()) {
pair cell = q.peek();
int x = cell.first;
int y = cell.second;
int v = grid[x][y];
System.out.print(grid[x][y] + " ");
// Go to the adjacent cells
for (int i = 0; i < 4; i++) {
int adjx = x + dRow[i];
int adjy = y + dCol[i];
if (isValid(vis, adjx, adjy)) {
if (grid[adjx][adjx] == v) {
q.add(new pair(adjx, adjy));
vis[adjx][adjy] = true;
}
}
}
}
public static void main(String[] args) {
// Given input matrix
int grid[][] = { .... };
ROW = grid.length;
COL = grid[0].length;
// Declare the visited array
boolean[][] vis = new boolean[ROW][COL];
BFS(grid, vis, 0, 0);
}
You need to iterate over the grid to identify the starting point of each BFS. Also, you need to initialize a new count at the start of each BFS and increment it each time you visit a neighboring cell. Then take the max of each such count.
static int max(int[][] grid)
{
int rows = grid.length;
int cols = grid[0].length;
Queue<Pos> q = new LinkedList<>();
boolean[][] visited = new boolean[rows][cols];
int max = 0;
for(int r=0; r<rows; r++)
{
for(int c=0; c<cols; c++)
{
if(!visited[r][c])
{
q.add(new Pos(r, c));
visited[r][c] = true;
int count = 0;
while(!q.isEmpty())
{
Pos p = q.poll();
count += 1;
for(int d=0; d<4; d++)
{
int i = p.r + dRow[d];
int j = p.c + dCol[d];
if(i >= 0 && i < rows && j >= 0 && j < cols && !visited[i][j] && grid[i][j] == grid[r][c])
{
q.add(new Pos(i, j));
visited[i][j] = true;
}
}
}
max = Math.max(max, count);
}
}
}
return max;
}
Test:
int[][] grid = {{1,2,3,4},
{1,2,4,4},
{4,2,4,5},
{6,9,4,7}};
System.out.printf("Max = %d%n", max(grid));
Output:
Max = 5
Bi Simple!
public static int findMaxAdjacentCount(int[][] grid) {
boolean[][] visited = createVisitGrid(grid);
int res = 0;
for (int row = 0; row < grid.length; row++)
for (int col = 0; col < grid[row].length; col++)
if (!visited[row][col])
res = Math.max(res, dfs(grid, visited, grid[row][col], row, col));
return res;
}
private static int dfs(int[][] grid, boolean[][] visited, int expected, int row, int col) {
if (row < 0 || row >= grid.length)
return 0;
if (col < 0 || col >= grid[row].length)
return 0;
if (visited[row][col] || grid[row][col] != expected)
return 0;
visited[row][col] = true;
int depth = 1;
depth += dfs(grid, visited, expected, row, col - 1);
depth += dfs(grid, visited, expected, row, col + 1);
depth += dfs(grid, visited, expected, row - 1, col);
depth += dfs(grid, visited, expected, row + 1, col);
return depth;
}
private static boolean[][] createVisitGrid(int[][] grid) {
boolean[][] visit = new boolean[grid.length][];
for (int row = 0; row < grid.length; row++)
visit[row] = new boolean[grid[row].length];
return visit;
}

one error in a code maxonebordersize.java [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 1 year ago.
the error ArrayIndexOutOfBoundsException in a loop
public class MaxOneBorderSize {
public static void setBorderMap(int[][] m, int[][] right, int[][] down) {
if(m == null){
return;
}
right = new int[m.length][m[0].length];
down = new int[m.length][m[0].length];
for(int row = 0; row <m.length;row++ ){
for(int col = 0; col <m[0].length; col++){
int index = 0;
int tempCol = col;
// 0 - N-1
while(tempCol<m[0].length && m[row][tempCol] == 1){
tempCol++;
index++;
}
right[row][tempCol-1] = index;
}
}
// 然后生成down的数据
for(int row = 0; row <m.length;row++ ){
for(int col = 0; col <m[0].length; col++){
int index = 0;
while(row<m.length&&m[row][col] == 1){
row++;
index++;
}
down[row-1][col] = index;
}
}
}
public static int getMaxSize(int[][] m) {
int[][] right = new int[m.length][m[0].length];
int[][] down = new int[m.length][m[0].length];
setBorderMap(m, right, down); // O(N^2); +
for (int size = Math.min(m.length, m[0].length); size != 0; size--) {
if (hasSizeOfBorder(size, right, down)) {
return size;
}
}
return 0;
}
public static boolean hasSizeOfBorder(int size, int[][] right, int[][] down) {
for (int i = 0; i != right.length - size + 1; i++) {
for (int j = 0; j != right[0].length - size + 1; j++) {
if (right[i][j] >= size && down[i][j] >= size
&& right[i + size - 1][j] >= size
&& down[i][j + size - 1] >= size) {
return true;
}
}
}
return false;
}
public static int[][] generateRandom01Matrix(int rowSize, int colSize) {
int[][] res = new int[rowSize][colSize];
for (int i = 0; i != rowSize; i++) {
for (int j = 0; j != colSize; j++) {
res[i][j] = (int) (Math.random() * 2);
}
}
return res;
}
public static void printMatrix(int[][] matrix) {
for (int i = 0; i != matrix.length; i++) {
for (int j = 0; j != matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] matrix = generateRandom01Matrix(7, 8);
printMatrix(matrix);
System.out.println(getMaxSize(matrix));
}
}
1 0 0 0 1 0 1 1
1 0 0 1 0 1 1 0
0 0 1 1 0 1 1 0
0 0 0 1 0 0 1 1
1 1 1 0 1 0 0 1
0 0 1 1 1 0 1 0
0 1 0 0 1 1 0 0
I have completed the code to get the longest side of the rectangle consists of ‘1’. But the error java.lang.ArrayIndexOutOfBoundsException has occured in
for(int row = 0; row <m.length;row++ ){
for(int col = 0; col <m[0].length; col++){
int index = 0;
int tempCol = col;
// 0 - N-1
while(tempCol<m[0].length && m[row][tempCol] == 1){
tempCol++;
index++;
}
right[row][tempCol-1] = index;
}
}
I don't have any idea about that.
In this line you have not handled exception for the condition tempCol = 0
which would make tempcol = -1 in the code and it will be out of bounds.
right[row][tempCol-1] = index;
There are two ways to handle this either use try catch or if else with proper condition
for(int row = 0; row <m.length;row++ ){
for(int col = 0; col <m[0].length; col++){
int index = 0;
int tempCol = col;
while(tempCol<m[0].length && m[row][tempCol] == 1){
tempCol++;
index++;
}
if(tempCol!=0){
right[row][tempCol-1] = index;
}
else{
right[row][tempCol] = index;
}
}
}
There is same problem with the down array which has row-1.
Also next time posting a question use proper proportionate indentation.
Exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at MaxOneBorderSize.setBorderMap(MaxOneBorderSize.java:25)
at MaxOneBorderSize.getMaxSize(MaxOneBorderSize.java:51)
at MaxOneBorderSize.main(MaxOneBorderSize.java:96)

Game of Life, java objects

On my program for java programming is not running right. My professor had us download a console.java to help use make a console to display our outputs of the program. I think the program is getting stuck when I am calling the update method and checkCells. My professor said that calling matrix.length for both rows and columns is incorrect but I'm stumped on how to call columns if I am not using matrix.length.
Any input is appreciated
import java.util.*;
public class Life {
private int birthLow = 0;
private int birthHigh = 0;
private int liveLow = 0;
private int liveHigh = 0;
private boolean[][] matrix;
public Life(long seed, int rows, int cols, int birthLow2, int birthHigh2, int liveLow2, int liveHigh2) {
boolean initalMatrix[][] = new boolean[rows][cols];
seedArray(initalMatrix, rows, cols, seed);
birthLow = birthLow2;
birthHigh = birthHigh2;
liveLow = liveLow2;
liveHigh = liveHigh2;
matrix = initalMatrix;
if ((rows < 1) && (cols < 1)) {
throw new IllegalArgumentException("Rows must be positive, not " + rows);
}
if ((rows > 9) && (cols < 9)) {
throw new IllegalArgumentException("Rows and cols cant go over 9, not " + rows + cols);
}
if (birthLow < 1 || (birthHigh > 9) || (liveLow < 1) || (liveHigh > 9)) {
throw new IllegalArgumentException("birth rates can not be below 1 or above 9 " + birthLow + birthHigh);
}
}
public boolean[][] world() {
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
return matrixClone;
}
public void update() {
matrix = checkCells(matrix, matrix.length, matrix.length, birthLow, birthHigh, liveLow, liveHigh);
}
public static void seedArray(boolean[][] matrix, int rows, int cols, long seed) {
// generates a random seed to fill the matrix
Random s = new Random(seed);
for (int r = 1; r < rows - 1; r++) {
for (int c = 1; c < cols - 1; c++) {
boolean x = s.nextBoolean();
matrix[r][c] = x;
}
}
}
public static void printBoard(boolean[][] matrix, int rows, int cols) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (matrix[r][c] == false && c == 0) {
System.out.print("- ");
} else if (matrix[r][c] == false && c > 0) {
System.out.print("- ");
} else if (matrix[r][c] == true) {
System.out.print("# ");
}
}
System.out.println();
}
System.out.println();
}
public static boolean[][] checkCells(boolean[][] matrix, int rows, int cols, int birthLow, int birthHigh,
int liveLow, int liveHigh) {
// clones matrix board
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
// determines if the living cell is going to live or die
for (int r = 1; r < rows; r++) {
for (int c = 1; c < cols; c++) {
if (neighbors(matrixClone, r, c) < liveLow || neighbors(matrixClone, r, c) > liveHigh || c == 0
|| r == 0 || c == cols - 1 || r == rows - 1) {
matrix[r][c] = false;
} else if (neighbors(matrixClone, r, c) >= birthLow && neighbors(matrixClone, r, c) <= birthHigh) {
matrix[r][c] = true;
}
}
}
return matrixClone;
}
public static int neighbors(boolean[][] matrixClone, int r, int c) {
int neighbors = 0;
// checks all neighbors for life or death
for (int rn = (r - 1); rn <= (r + 1); rn++) {
for (int cn = (c - 1); cn <= (c + 1); cn++) {
try {
if (matrixClone[rn][cn] == true) {
neighbors++;
}
// catches the array if it checks out the perimeter
} catch (ArrayIndexOutOfBoundsException f) {
continue;
}
}
}
return neighbors;
}
}
Don't use matrix.length for columns. You already know that. The reason is that it gives you the number of rows. Instead, just save the values of row and col and use them.
One way to do that is to make them fields, and initialize them in your constructor.
Do not initialize a random boolean[][] called initialMatrix. Instead, initialize the boolean[][] matrix that you have in the fields up above (matrix = new boolean[rows][cols]). Then for seedArray, call seedArray(matrix, rows, cols, seed).
Finally, in the update() method, do not use matrix.length, but rather rows and cols.

Top to bottom for numbered triangle [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
Below I had tried to come up with a method to find the path to figure out the shortest path but every time I run the program I get a nullpointer exception at the findshortestPath1 at the int cols = myArray[rows].length I don't know how to solve this problem. If you have other methods I can try to solve this, tha twill be greatly appreciated.
*******UPDATE******* Okay I updated that code with your suggestions, but I was still getting problems at
minCosts[0] = myArray[row][col]
and
findShortestPath(myArray, minCosts, row, col);
Code:
import java.util.Random;
public class Triangle{
public static void createTriangle(int numRows){
int rows=numRows;
int max =9, min =2;
int[][] myArray = new int[rows][];
Random random = new Random();
for (int i = 0; i < rows; i++) {
myArray[i]= new int[i+1];
//Below is used for organizing the triangle
System.out.println("");
for(int p=rows-i; p>0;p--)
System.out.print(" ");
for (int j = 0; j <=i; j++) {
//below puts the spacing between each column in the triangle
System.out.print(" ");
myArray[i][j] = random.nextInt(max - min + 1) + min;
System.out.print(myArray[i][j]);
System.out.print(" ("+i+", "+j+") ");
}
}
}
public static int findShortestPath1(int numRows) {
int rows= numRows;
int[][] myArray = new int[rows][];
int numNodes = sumToN(rows);
int[] minCosts = new int[numNodes];
for(int row = 0; row<rows; row++) {
int cols = new int[rows].length;
for(int col = 0; col< cols; col++) {
findShortestPath(myArray, minCosts, row, col);
}
}
int row = rows;
int cols = new int[rows].length;
int min1 = -1;
for(int col = 0; col<cols; col++) {
int cost = minCosts[indexFromRowCol(rows,col)];
if(cost < min1 || min1 ==-1) {
min1 = cost;
}
}
return Math.max(0, min1);
}
private static int findShortestPath(int[][] myArray, int[] minCosts, int row, int col) {
if (row == 0) {
minCosts[0] = myArray[row][col];
return minCosts[0];
}
int minValue = -1;
if (col - 1 >= 0) {
minValue = minCosts[indexFromRowCol(row - 1, col - 1)];
}
if (col < myArray[row - 1].length) {
int cost = minCosts[indexFromRowCol(row - 1, col)];
if (minValue == -1) {
minValue = cost;
}
minValue = Math.min(minValue, cost);
}
int minCost = myArray[row][col] + minValue;
minCosts[indexFromRowCol(row, col)] = minCost;
return minCost;
}
private static int sumToN(int n) {
if (n < 0) {
return 0;
}
return n * (n + 1) / 2;
}
private static int indexFromRowCol(int row, int col) {
return sumToN(row) + col;
}
}
This:
for(int row = 0; row >= rows; row++)
Should be:
for(int row = 0; row < rows; row++)
Suppose, for example, that rows = 10. Then row >= rows is equivalent to 0 >= 10, which is false, so the for loop never runs.
When you do:
int row = rows - 1;
int cols = myArray[row].length;
You will get row = 9 but, since the for loop didn't execute, myArray is still empty. So you get a NullPointerException when you try to access myArray[9].length.
Another problem is that, since you did not initialize the size of the second dimension when you did:
int[][] myArray = new int[rows][];
You will still get a NullPointerException inside the for loop when you try to do:
int cols = myArray[row].length;
So you probably want to initialize myArray in findShortestPath1() the same way you did in createTriangle().

8 Queens Not Using the Backtracking Method

I am doing a version of the 8 queens problem, but not using the backtracking method. For one of the methods, I have to "score the square", basically I need to find the number of cells that would become unavailable were there to be a queen placed in the box. My problem is that I cannot get my code to return the score of the square. Is there something wrong with my for loops or something?
import java.util.ArrayList;
public class Chessboard {
private int[][] board;
public static final int QUEEN = -2;
public static final int SQUIGGLE = -1;
/**
* constructor initializes board to be of size n-by-n and containing all
* zeros
*/
public Chessboard(int n) {
board = new int[n][n];
}
/**
* returns the board
*/
public int[][] getBoard() {
return board;
}
/**
* returns SQUIGGLE if square at row, col contains SQUIGGLE returns QUEEN if
* square at row, col contains QUEEN otherwise, counts the number of squares
* that would become unavailable if the square at row, col were to receive a
* queen; this count is returned
*/
public int scoreSquare(int row, int col) {
if (board[row][col] == -1) {
return SQUIGGLE;
} else if (board[row][col] == -2) {
return QUEEN;
}
else {
int countsquare = 1;
for (int r = 0; r < board[col].length; r++) {
countsquare++;
}
for (int c = 0; c < board[row].length; c++) {
countsquare++;
}
for (int r = row + 1, c = col + 1; r < board.length
&& c < board.length; r++, c++) {
countsquare++;
}
for (int r = row + 1, c = col - 1; r < board.length && c < 0; r++, c--) {
countsquare++;
}
for (int r = row - 1, c = col + 1; r < 0 && c < board.length; r--, c++) {
countsquare++;
}
for (int r = row - 1, c = col - 1; r < 0 && c < 0; r--, c--) {
countsquare++;
}
return countsquare;
}
}
In every loop where you compare r or c to zero, you need to use >= instead of <. For example, in this loop, you need to use c >= 0 as opposed to c < 0:
for (int r = row + 1, c = col - 1; r < board.length && c < 0; r++, c--) {
This is because you are counting down to zero and so you want to keep counting while your counter is above zero.
Finally, although it shouldn't affect your results, you don't really need your first two loops as each of them should just result in adding n (which is board.length, i.e., the size of any row or column).

Categories