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)
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;
}
}
This question already has answers here:
Syntax for creating a two-dimensional array in Java
(13 answers)
Closed 3 years ago.
I am working with 2-D arrays and I require help on this topic. My task is to create a 2-D array such that it is n by n (i.e. the number of rows and columns are equal). Fill the array with alternating 0's and 1's
void setup()
{
int n=3;
// code to populate the array
// code to display the output of array in a table format
/* output should be as follows:
The expected result when n=3 should be as the following:
1 0 1
0 1 0
1 0 1
*/
}
Solution:
class test{
public static void main(String[] args) {
int n = 3;
int[][] arr = setup(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(arr[i][j]);
}
System.out.println();
}
}
static int[][] setup(int n){
int[][] arr = new int [n][n];
boolean even = false;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = even ? 1 : 0;
even = !even;
}
}
return arr;
}
}
Output:
0 1 0
1 0 1
0 1 0
This should work.
You can replace the 3 that is given to n with any number you want as the 2D-Array's length.
void setup(){
int n = 3;
int count = 0;
int[][] myArray = new int[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(count % 2 == 0){
myArray[i][j] = 1;
}
else{
myArray[i][j] = 0;
}
System.out.print(myArray[i][j] + " ");
count++;
}
System.out.println();
}
}
Output:
0 1 0
1 0 1
0 1 0
It's not complex, you just have to iterate two loops, that's it. Although you can get the solution on different ways.
public static void main(String[] args) {
int n = 3;
int [][] arr = new int[n][n];
int val = 1;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
arr[i][j] = val;
val = (val == 0) ? 1 : 0;
}
}
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
Output:
0 1 0
1 0 1
0 1 0
A simple implementation:
void setup()
{
int n=3;
final int[][] array = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((n * i + j) % 2 == 0) {
array[i][j] = 1;
}
}
}
}
Here is how you can approach your logic , create a counter and negate each time after it prints value.
public static void main(String[] args) {
int counter = 0;
int n = 3;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.print(counter==0?1:0);
counter = ~counter;
}
System.out.println();
}
}
Output
101
010
101
Here is Online source code.
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);
I'm trying to make a knight's tour program but when I try to subtract from the row/column in the 2d array for the board so I move around the board. But everything I try to do it keeps trying to set the board to -1 instead of subtracting 1.
Kind of hard to explain what the problem is, but if anyone could help me out here that would be well appreciated here's my code:
public class Knight1 {
public static void main(String[] args) {
int board[][] = new int[8][8];
int horizontal[] = new int[8];
int vertical[] = new int[8];
horizontal[0] = 2;
horizontal[1] = 1;
horizontal[2] = -1;
horizontal[3] = -2;
horizontal[4] = -2;
horizontal[5] = -1;
horizontal[6] = 1;
horizontal[7] = 2;
vertical[0] = -1;
vertical[1] = -2;
vertical[2] = -2;
vertical[3] = -1;
vertical[4] = 1;
vertical[5] = 2;
vertical[6] = 2;
vertical[7] = 1;
int move = 1;
int moveNumber = 0;
int currentRow = 0;
int currentCol = 0;
int counter = 1;
while (moveNumber != 7) {
currentRow += vertical[moveNumber];
currentCol += horizontal[moveNumber];
board[currentRow][currentCol] = counter;
moveNumber++;
counter++;
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
Problem come up on this point:
int currentRow = 0;
int currentCol = 0;
You are trying to add -1 to currentRow variable
vertical[0] = -1;
currentRow += vertical[moveNumber];
I just look at Knight's tour problem and your code. If I understood both of them correctly, you should start from ROW 7 and COLUMN 4.
So only change this two variable:
int currentRow = 7;
int currentCol = 4;
It is going to compile this result:
0 0 0 0 0 0 0 0
0 0 0 0 4 0 0 0
0 0 5 0 0 0 3 0
0 0 0 0 0 0 0 0
0 6 0 0 0 0 0 2
0 0 0 0 0 0 0 0
0 0 7 0 0 0 1 0
0 0 0 0 0 0 0 0
I also edited your main method a little bit:
You don't need to horizontal and vertical arrays. You can do it with multi-dimensional arrays.
public static void main(String[] args) {
int board[][] = new int[8][8];
int moveNumber = 0;
int currentRow = 7;
int currentCol = 4;
int counter = 1;
//moves[moveNumber][0] = columnValues;
//moves[moveNumber][1] = rowValues;
int moves[][] = new int[][]{{ 2,-1},
{ 1,-2},
{-1,-2},
{-2,-1},
{-2, 1},
{-1, 2},
{ 1, 2},
{ 2, 1}};
while (moveNumber != 7) {
currentCol += moves[moveNumber][0];
currentRow += moves[moveNumber][1];
board[currentRow][currentCol] = counter;
moveNumber++;
counter++;
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++)
System.out.print(board[i][j] + " ");
System.out.println();
}
}
I am a beginner at Java programming (1st semester) and I have been writing code for the Game of Life. I am counting the surrounding cells of each cell in a two-dimensional array. I have reached the point where the program compiles well, but when I test it with different sizes of the array, I can see that the count of the cells is not correct, although the consequent swapping of the cells' status is performed correctly, and I cannot figure out how this can be. Please help:
public static void surrounding(boolean[][] around) {
for (int i = 0; i < around.length; i++)
for (int j = 0; j < around[i].length; j++) {
int minRow = i == 0 ? i : i - 1;
int maxRow = i == (around[i].length - 1) ? around[i].length - 1 : i + 1;
int minCol = j == 0 ? j : j - 1;
int maxCol = j == (around[i].length - 1) ? around[i].length - 1 : j + 1;
int count = 0;
for (int a = minRow; a <= maxRow; a++)
for (int b = minCol; b <= maxCol; b++) {
if ((around[a][b]) && !(a == i && b == j))
count++;
}
System.out.print(count + " ");
if ((around [i][j]) && (count < 2 || count > 3))
around[i][j] = false;
else if (!(around[i][j]) && (count == 3))
around[i][j] = true;
}
System.out.println();
for (int row = 0; row < around.length; row++) {
for(int column = 0; column < around[row].length; column++) {
if (around[row][column])
System.out.print("X ");
else
System.out.print(". ");
}
System.out.println();
}
}
And here is the whole program so far:
public static void main(String[] args) {
boolean[][] world = randomBools(3);
for (int row = 0; row < world.length; row++) {
for(int column = 0; column < world[row].length; column++) {
if (world[row][column])
System.out.print("X ");
else
System.out.print(". ");
}
System.out.println();
}
System.out.println();
surrounding(world);
}
public static boolean[][] randomBools(int len) {
Random random = new Random();
boolean[][] arr = new boolean[len][len];
for(int i = 0; i < len; i++)
for(int j = 0; j < arr[i].length; j++)
arr[i][j] = random.nextBoolean();
return arr;
}
public static void surrounding(boolean[][] around) {
for (int i = 0; i < around.length; i++)
for (int j = 0; j < around[i].length; j++) {
int minRow = i == 0 ? i : i - 1;
int maxRow = i == (around[i].length - 1) ? around[i].length - 1 : i + 1;
int minCol = j == 0 ? j : j - 1;
int maxCol = j == (around[i].length - 1) ? around[i].length - 1 : j + 1;
int count = 0;
for (int a = minRow; a <= maxRow; a++)
for (int b = minCol; b <= maxCol; b++) {
if ((around[a][b]) && !(a == i && b == j))
count++;
}
System.out.print(count + " ");
if ((around [i][j]) && (count < 2 || count > 3))
around[i][j] = false;
else if (!(around[i][j]) && (count == 3))
around[i][j] = true;
}
System.out.println();
for (int row = 0; row < around.length; row++) {
for(int column = 0; column < around[row].length; column++) {
if (around[row][column])
System.out.print("X ");
else
System.out.print(". ");
}
System.out.println();
}
}
}
You use
int minRow = i == 0 ? i : i - 1;
int maxRow = i == (around[i].length - 1) ? around[i].length - 1 : i + 1;
int minCol = j == 0 ? j : j - 1;
int maxCol = j == (around[i].length - 1) ? around[i].length - 1 : j + 1;
,but it has to be
int minRow= Math.max(0,i-1);
int maxRow= Math.min(around.length-1,i+1);
int minCol= Math.max(0,j-1);
int maxCol = Math.min(around[i].length-1,j+1);
Since around is a n*n matrix with equaly long side you can use
int maxCol=Math.min(around.length-1,j+1);
Also you can put maxRow and minRow one for loop higher( the loop with i as counter) since maxRow and minRow don't change for the same i.
for (int a = minRow; a <= maxRow; a++)
for (int b = minCol; b <= maxCol; b++) {
if ((around[a][b]) && !(a == i && b == j))
count++;
}
System.out.print(count + " ");
You count the current cell too. you should change this to:
if(a!=0&&b!=0) count++;