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;
}
Related
I'm trying to solve this problem: https://leetcode.com/problems/rotting-oranges/
The link explains better than I can with the visuals, but basically you have to make every orange that's next to a "rotten" one (value 2) rotten as well.
I'm approaching this using a BFS. I start by making a queue for all the rotten oranges, then I pass that to my bfs function which checks if going (up/down/left/right) is possible and if it is then adds that to the queue and changes the value to show the node has already been visited.
My solution is not giving me the right answer and I'm not sure where the logical misstep is.
class Solution {
public int orangesRotting(int[][] grid) {
//get all 2's into a queue
//iterate over 2 making all oranges rotten
//iterate grid again --> anything that's not 2, return -1
//else return count
Queue<String> q = new LinkedList<>();
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[i].length; j++) {
if(grid[i][j] == 2) {
q.add("" + i + j);
}
}
}
int count = getMinutes(grid, q);
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[i].length; j++) {
if(grid[i][j] == 1) {
return -1;
}
}
}
return count;
}
public static int getMinutes(int[][] grid, Queue<String> q) {
Queue<String> rotten = new LinkedList<>();
int count = 0;
final int[][] SHIFTS = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
while(true) {
while(!q.isEmpty()) {
String s = q.remove();
int i = Integer.parseInt(s.substring(0, s.length() - 1));
int j = Integer.parseInt(s.substring(s.length() - 1));
for(int[] points : SHIFTS) {
int tempI = i + points[0];
int tempJ = j + points[1];
if(isValidMove(grid, tempI, tempJ)) {
rotten.add("" + tempI + tempJ);
grid[tempI][tempJ] = 2; //it's visited
}
}
}
if(rotten.isEmpty()) {
return count;
}
count++;
q = rotten;
}
}
public static boolean isValidMove(int[][] grid, int i, int j) {
if(i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] != 1) {
return false;
}
return true;
}
}
I suggest you don't do this : q.add("" + i + j); How would you distinguish between {11,2} and {1, 12}, both give the same string "112"? Just use q.add( new int[]{i, j} ) it shouldn't cause too much of a performance problem they are just ints. In fact its the other way around. It should be faster.
Now coming to the main issue, your algorithm is almost correct except for the fact that you need to initialize a new Queue inside while ( true ) because you have to start with a new queue every time you flush your current queue. The idea is you start with a queue of already rotten oranges. Rot their neighboring oranges and build a new queue consisting of the newly rotten oranges. Then repeat until your new queue of newly rotten oranges is empty. So it has to be a new queue everytime you start with already rotten oranges.
The modified getMinutes with the correction of the main issue is :
public static int getMinutes(int[][] grid, Queue<String> q) {
int count = 0;
final int[][] SHIFTS = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
while(true) {
Queue<String> rotten = new LinkedList<>();
while(!q.isEmpty()) {
String s = q.remove();
int i = Integer.parseInt(s.substring(0, s.length() - 1));
int j = Integer.parseInt(s.substring(s.length() - 1));
for(int[] points : SHIFTS) {
int tempI = i + points[0];
int tempJ = j + points[1];
if(isValidMove(grid, tempI, tempJ)) {
rotten.add("" + tempI + tempJ);
grid[tempI][tempJ] = 2; //it's visited
}
}
}
if(rotten.isEmpty()) {
return count;
}
count++;
q = rotten;
}
}
Looks pretty good!
My guess is that your solution is missing return 0 for if there is no freshOranges early.
This is similarly a Breadth First Search algorithm, crammed into one function though for laziness purposes ( ˆ_ˆ ):
public class Solution {
private static final int[][] directions = new int[][] {
{1, 0},
{ -1, 0},
{0, 1},
{0, -1}
};
public static final int orangesRotting(
int[][] grid
) {
final int rows = grid.length;
final int cols = rows > 0 ? grid[0].length : 0;
if (rows == 0 || cols == 0) {
return 0;
}
Queue<int[]> queue = new LinkedList<>();
int freshOranges = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (grid[row][col] == 2) {
queue.offer(new int[] {row, col});
} else if (grid[row][col] == 1) {
freshOranges++;
}
}
}
if (freshOranges == 0) {
return 0;
}
int count = 0;
while (!queue.isEmpty()) {
count++;
final int size = queue.size();
for (int i = 0; i < size; i++) {
final int[] cell = queue.poll();
for (int[] direction : directions) {
final int row = cell[0] + direction[0];
final int col = cell[1] + direction[1];
if (
row < 0 ||
col < 0 ||
row >= rows ||
col >= cols ||
grid[row][col] == 0 ||
grid[row][col] == 2
) {
continue;
}
grid[row][col] = 2;
queue.offer(new int[] {row, col});
freshOranges--;
}
}
}
return freshOranges == 0 ? count - 1 : -1;
}
}
Given a matrix of dimension r*c where each cell in the matrix can have values 0, 1 or 2 which has the following meaning:
0 : Empty cell
1 : Cells have fresh oranges
2 : Cells have rotten oranges
So, we have to determine what is the minimum time required to rot all oranges. A rotten orange at index [i,j] can rot other fresh orange at indexes [i-1,j], [i+1,j], [i,j-1], [i,j+1] (up, down, left and right) in unit time. If it is impossible to rot every orange then simply return -1.
Input:
The first line of input contains an integer T denoting the number of test cases. Each test case contains two integers r and c, where r is the number of rows and c is the number of columns in the array a[]. Next line contains space separated r*c elements each in the array a[].
Here is the Code I have written
class GFG {
public static boolean isSafe(int[][] M, boolean[][] visited, int i, int j) {
int R = M.length;
int C = M[0].length;
return (i >= 0 && i < R && j >= 0 && j < C && (!visited[i][j]) && M[i][j] != 0);
}
public static int findMinDist(int[][] M, boolean[][] visited, int i, int j, int dist) {
if (M[i][j] == 2)
return dist;
int[] x_pos = { 1, -1, 0, 0 };
int[] y_pos = { 0, 0, -1, 1 };
visited[i][j] = true;
int min = Integer.MAX_VALUE;
for (int k = 0; k < 4; k++) {
if (isSafe(M, visited, i + x_pos[k], j + y_pos[k]))
min = Math.min(min, findMinDist(M, visited, i + x_pos[k], j + y_pos[k], dist + 1));
}
return min;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int t = 0; t < T; t++) {
int R = sc.nextInt();
int C = sc.nextInt();
int[][] M = new int[R][C];
boolean[][] visited = new boolean[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
M[i][j] = sc.nextInt();
}
}
int[][] time = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (M[i][j] == 1)
time[i][j] = findMinDist(M, new boolean[R][C], i, j, 0);
}
}
int maxTime = Integer.MIN_VALUE;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
maxTime = Math.max(time[i][j], maxTime);
}
}
System.out.println(maxTime == Integer.MAX_VALUE ? -1 : maxTime);
}
}
}
I am trying to find minimum distance of 2 from each 1.
It is not working for test case
Input:
1
2 5
1 1 1 1 1 0 2 1 1 1
Its Correct output is:
4
And My Code's output is:
6
Please suggest what's wrong with the code.
Start by creating a matrix to store the times the oranges rot. You can initialize all slots with -1. You will use BFS but you won't need a "marked" matrix, because the times the oranges rot will already be enough to tell you if a slot has been visited or not.
Iterate through the original matrix. When you find a value 2, do a BFS starting there to rot the fresh oranges. This BFS should also state the time when each orange is rot and you must always keep the smallest time. If the orange being looked at the moment was already rotten at time t1 and you've just got there in time t2, where t2 < t1, pretend this orange is fresh and put it into the BFS queue like so.
After finishing it, iterate through the matrix of times and return the biggest value found.
class Pair {
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public int x;
public int y;
}
public class Solution {
public static boolean isSafe(int x, int y, int r, int c) {
return (x >= 0) && (x < r) && (y >= 0) && (y < c);
}
public static boolean isFreshOrageLeft(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 1)
return true;
}
}
return false;
}
public static int orangesRotting(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
int count = 0;
boolean flag = false;
Queue<Pair> q = new LinkedList<>();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 2)
q.add(new Pair(i, j));
}
}
q.add(new Pair(-1, -1));
while (!q.isEmpty()) {
while (q.peek().x != -1 && q.peek().y != -1) {
Pair p = q.poll();
int leftX = p.x - 1;
int leftY = p.y;
if (isSafe(leftX, leftY, r, c) && grid[leftX][leftY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[leftX][leftY] = 2;
q.add(new Pair(leftX, leftY));
}
int rightX = p.x + 1;
int rightY = p.y;
if (isSafe(rightX, rightY, r, c) && grid[rightX][rightY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[rightX][rightY] = 2;
q.add(new Pair(rightX, rightY));
}
int upX = p.x;
int upY = p.y + 1;
if (isSafe(upX, upY, r, c) && grid[upX][upY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[upX][upY] = 2;
q.add(new Pair(upX, upY));
}
int downX = p.x;
int downY = p.y - 1;
if (isSafe(downX, downY, r, c) && grid[downX][downY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[downX][downY] = 2;
q.add(new Pair(downX, downY));
}
}
flag = false;
q.poll();
if (!q.isEmpty())
q.add(new Pair(-1, -1));
}
return isFreshOrageLeft(grid)?-1:count;
}
public static void main(String[] args) {
int[][] grid = {{2,2,0,1}};
System.out.println(orangesRotting(grid));
}
}
https://judge.telerikacademy.com/problem/29largestareamatrix
That's the exercise.
Write a program that finds the largest area of equal neighbour elements in a rectangular matrix and prints its size.
Input
On the first line you will receive the numbers N and M separated by a single space
On the next N lines there will be M numbers separated with spaces - the elements of the matrix
Output
Print the size of the largest area of equal neighbour elements
Constraints
3 <= N, M <= 1024
Time limit: 0.5s for JAVA
Memory limit: 50MB
And this is my solution.
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static class Node {
private int rowIndex, colIndex;
Node(int rowIndex, int colIndex) {
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
Node[] getNeighbourNodes(int maxRowIndex, int maxColIndex) {
Node[] nodes = new Node[4];
int[][] indexesToCheck = {
{rowIndex - 1, colIndex},
{maxRowIndex - 1, colIndex},
{rowIndex + 1, colIndex},
{0, colIndex},
{rowIndex, colIndex - 1},
{rowIndex, maxColIndex - 1},
{rowIndex, colIndex + 1},
{rowIndex, 0}
};
for (int i = 0; i < indexesToCheck.length; i += 2) {
int rowIndex = indexesToCheck[i][0], backupRowIndex = indexesToCheck[i + 1][0];
int colIndex = indexesToCheck[i][1], backupColIndex = indexesToCheck[i + 1][1];
if (indexExists(rowIndex, colIndex, maxRowIndex, maxColIndex)) {
nodes[i / 2] = new Node(rowIndex, colIndex);
} else {
nodes[i / 2] = new Node(backupRowIndex, backupColIndex);
}
}
return nodes;
}
private boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
}
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int n = keyboard.nextInt();
int m = keyboard.nextInt();
int[][] matrix = new int[n][m];
boolean[][] visitedElements = new boolean[n][m];
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
matrix[row][col] = keyboard.nextInt();
}
}
int maxCounter = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
if (!visitedElements[row][col]) {
maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
}
}
}
System.out.println(maxCounter);
}
private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] visitedElements, int maxRowIndex, int maxColIndex) {
Stack<Node> stack = new Stack<>();
stack.push(new Node(row, col));
visitedElements[row][col] = true;
int counter = 1;
while (stack.size() > 0) {
Node currentNode = stack.pop();
row = currentNode.rowIndex;
col = currentNode.colIndex;
Node[] neighboursIndexes = currentNode.getNeighbourNodes(maxRowIndex, maxColIndex);
for (Node node : neighboursIndexes) {
if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
stack.push(node);
visitedElements[node.rowIndex][node.colIndex] = true;
counter++;
}
}
}
return counter;
}
}
I tried without Node class and with BufferedReader and I still get Time limit exception.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] firstLine = br.readLine().split(" ");
int n = Integer.parseInt(firstLine[0]);
int m = Integer.parseInt(firstLine[1]);
int[][] matrix = new int[n][m];
boolean[][] visitedElements = new boolean[n][m];
for (int row = 0; row < n; row++) {
String[] line = br.readLine().split("\\s");
matrix[row] = Arrays.stream(line).mapToInt(Integer::parseInt).toArray();
}
int maxCounter = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
if (!visitedElements[row][col]) {
maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
}
}
}
System.out.println(maxCounter);
}
private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] checkedElements, int maxRowIndex, int maxColIndex) {
Stack<Integer[]> stack = new Stack<>();
stack.push(new Integer[]{row, col});
checkedElements[row][col] = true;
int counter = 1;
while (stack.size() > 0) {
Integer[] elementIndexes = stack.pop();
row = elementIndexes[0];
col = elementIndexes[1];
int[][] neighboursIndexes = getNeighbourNodes(row, col, maxRowIndex, maxColIndex);
for (int[] indexes : neighboursIndexes) {
int neighbourRow = indexes[0];
int neighbourCol = indexes[1];
if (!checkedElements[neighbourRow][neighbourCol] && matrix[row][col] == matrix[neighbourRow][neighbourCol]) {
stack.push(new Integer[]{neighbourRow, neighbourCol});
checkedElements[neighbourRow][neighbourCol] = true;
counter++;
}
}
}
return counter;
}
private static int[][] getNeighbourNodes(int rowIndex, int colIndex, int maxRowIndex, int maxColIndex) {
int[][] indexes = new int[4][];
if (indexExists(rowIndex - 1, colIndex, maxRowIndex, maxColIndex)) {
indexes[0] = new int[]{rowIndex - 1, colIndex};
} else {
indexes[0] = new int[]{maxRowIndex - 1, colIndex};
}
if (indexExists(rowIndex + 1, colIndex, maxRowIndex, maxColIndex)) {
indexes[1] = new int[]{rowIndex + 1, colIndex};
} else {
indexes[1] = new int[]{0, colIndex};
}
if (indexExists(rowIndex, colIndex - 1, maxRowIndex, maxColIndex)) {
indexes[2] = new int[]{rowIndex, colIndex - 1};
} else {
indexes[2] = new int[]{rowIndex, maxColIndex - 1};
}
if (indexExists(rowIndex, colIndex + 1, maxRowIndex, maxColIndex)) {
indexes[3] = new int[]{rowIndex, colIndex + 1};
} else {
indexes[3] = new int[]{rowIndex, 0};
}
return indexes;
}
private static boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
}
}
In this code snippet,
if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
visitedElements[row][col] = true;
counter++;
stack.push(node);
}
you are doing visitedElements[row][col] = true; which is actually making the current index itself true again. So, it's neighbours are never getting a chance to be true and adding each other all the time. Hence, it's a time limit exceeded(as your code looks accurate).
Change visitedElements[row][col] = true; to visitedElements[node.rowIndex][node.colIndex] = true;
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);
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().