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().
Related
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;
}
I have an array of size m rows n columns with each cell size is considered as 1x1.
Now I am removing a list of rows and columns from this array, next I want to know the biggest gap that can be formed after removing them.
Example:
Array of size 4 rows and 3 columns, now I am removing rows {1,2,3} and columns {1,2}
This results is an array having biggest gap of 12 cells.
Another Example:
Array of size 4 rows and 4 columns, now I am removing rows {2} and columns {2}
This results is an array having biggest gap of 4 cells.
I have come up with below code that works for this example:
static long process(int n, int m, int[] h, int[] v) {
ArrayList<ArrayList<Long>> array = new ArrayList<ArrayList<Long>>();
for (int r = 0; r <= n; r++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int c = 0; c <= m; c++) {
temp.add((long) 1);
}
array.add(temp);
}
int[] x = h;
int xnum = x.length;
Arrays.sort(x);
int[] y = v;
int ynum = y.length;
Arrays.sort(y);
// removing bar i means that list at i-1 and at i
for (int a = xnum - 1; a >= 0; a--) {
int i = x[a];
for (int cell = 0; cell < array.get(i).size(); cell++) {
array.get(i).set(cell, array.get(i).get(cell) + array.get(i - 1).get(cell));
}
array.remove(i - 1);
}
ArrayList<ArrayList<Long>> newarray = new ArrayList<ArrayList<Long>>();
for (int col = 0; col < array.get(0).size(); col++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int row = 0; row < array.size(); row++) {
temp.add(array.get(row).get(col));
}
newarray.add(temp);
}
for (int b = ynum - 1; b >= 0; b--) {
int i = y[b];
for (int cell = 0; cell < newarray.get(i).size(); cell++) {
newarray.get(i).set(cell, newarray.get(i).get(cell) + newarray.get(i - 1).get(cell));
}
newarray.remove(i - 1);
}
long max = 1;
for (ArrayList<Long> arr : newarray) {
for (long num : arr) {
if (num > max)
max = num;
}
}
return max;
}
How can we reduce the time complexity of this code, because the size of rows and columns is:
1 <= rows, columns <= 100000
Let's start by looking at your current solution, by using simple array instead of ArrayList we can reduce this code to:
static long process(int rows, int cols, int[] hor, int[] ver) {
final long[][] a = new long[rows][cols];
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) a[i][j] = 1;
for (int h : hor) for (int j = 0; j < cols; j++) a[h - 1][j] = a[h][j] = a[h - 1][j] + a[h][j];
for (int v : ver) for (int i = 0; i < rows; i++) a[i][v - 1] = a[i][v] = a[i][v - 1] + a[i][v];
long max = 0;
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) max = Math.max(max, a[i][j]);
return max;
}
this code has complexity O(N^2)
but, we should understand that biggest gap will be in place where biggest count of consecutive rows and columns are removed, thus we can simplify algorithm to:
static int maxConsecutive(int[] a) {
Arrays.sort(a);
int max = 0;
int start = 0;
for (int i = 0; i < a.length; i++)
if (a[i] - a[start] == i - start) max = Math.max(max, i - start + 1);
else start = i;
return max;
}
static long process(int rows, int cols, int[] hor, int[] ver) {
long maxH = maxConsecutive(hor);
long maxV = maxConsecutive(ver);
return (maxH + 1) * (maxV + 1);
}
which has complexity O(logN)
I am implementing N-Queen problem solver with backjumping algorithm and I have caught infinite loop error in recursive call.
I have mainly caused trouble in returning function.I think I have error in designing recursive calls.
package Backjumping;
import org.python.google.common.primitives.Ints;
import java.util.*;
public class Backjumping {
int size;
List<Integer> columns;
int numberofplaces;
int numberofbacktracks;
HashMap<Integer, List<Integer>> conflict;
boolean noBreak = true;
Backjumping(int size) {
this.size = size;
columns = new ArrayList();
conflict = new HashMap<>(size);
for (int i = 0; i < size; i++) {
conflict.put(i, new ArrayList<>());
}
}
List place(int startRow) {
if (columns.size() == size) {
System.out.println("Solution Found! The board size was :" + size);
System.out.println(numberofplaces + " total nodes assigned were made.");
System.out.println(numberofbacktracks + " total backtracks were executed.");
return this.columns;
} else {
for (int row = 0; row < size; row++) {
if (isSafe(columns.size(), row)) {
if (indexExists(columns, columns.size()))
columns.set(columns.size(), row);
else
columns.add(columns.size(), row);
numberofplaces += 1;
return place(startRow);
}
}
if (noBreak) {
List<Integer> max_check = conflict.get(columns.size());
int lastRow = Collections.min(max_check);
numberofbacktracks += 1;
conflict.replace(columns.size(), new ArrayList<>());
int previous_variable = columns.remove(lastRow);
return place(previous_variable);
}
}
return this.columns;
}
private boolean isSafe(int cols, int rows) {
for (int threatrow : columns) {
int threatcol = columns.indexOf(threatrow);
if (rows == threatrow || cols == columns.indexOf(threatrow)) {
(conflict.get(cols)).add(threatcol);
return false;
} else if ((threatrow + threatcol) == (rows + cols) || (threatrow - threatcol) == (rows - cols)) {
(conflict.get(cols)).add(threatcol);
return false;
}
}
return true;
}
public boolean indexExists(final List list, final int index) {
return index >= 0 && index < list.size();
}
public static void main(String[] args) {
System.out.println("Enter the size of board");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Backjumping bj = new Backjumping(n);
double start = System.currentTimeMillis();
List cols = bj.place(0);
double end = System.currentTimeMillis();
System.out.println("Time to solve in second = " + (end - start) * 0.001 + " s");
System.out.print("Ths solution is : ");
cols.forEach(i -> System.out.print(((int) i + 1) + ", "));
System.out.println("\n\nPlotting CSP result on N_Queens board");
System.out.println("......................................\n");
bj.getBoardPic(n, cols);
}
public void getBoardPic(int size, List columns) {
int[] cols = Ints.toArray(columns);
int[][] matrix = new int[size][size];
for (int a = 0; a < size; a++) {
int j = cols[a];
matrix[a][j] = 1;
}
for (int a = 0; a < size; a++) {
for (int b = 0; b < size; b++) {
if (matrix[b][a] == 1)
System.out.print(" Q ");
else
System.out.print(" - ");
}
System.out.println();
}
}
}
The main errors are that when I assign row=0 in for (int row = 0; row < size; row++) the input size of n=6 goes wrong and other values are right.
When I assign row=startrow in for (int row = startrow; row < size; row++) the input size of n=6 goes right and other values are wrong.
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 need help with sorting Random numbers into a 2D array. I have to generate 50 random numbers into a column of the array, then sort the numbers in order (ascending or descending). This is what I have so far and am so lost. Please Help.
UPDATED VERSION
public static void main(String[] args)
{
int rows = 2;
int columns = 50;
int[][] anArray = new int[rows][columns];
Random rand = new Random();
for (int i = 0; i < anArray.length; i++)
{
for (int j = 0; j < anArray[0].length; j++)
{
int n = rand.nextInt(100);
anArray[i][j] = n;
}
}
int []temp;
for (int i=0;i<anArray.length;i++)
{
for (int j=0;j<anArray.length-i;j++ )
{
if (anArray[i][j]>anArray[i][j+1])
{
temp =anArray[j];
anArray[j+1]=anArray[j];
anArray[j+1]=temp;
}
}
}
for (int i = 0; i < anArray.length; i++)
{
for (int j=0;j<anArray.length-i;j++ )
{
System.out.println(anArray[i][j]);
}
}
}
}
You can sort 2D arrays on their initial element using a custom Comparator:
Arrays.sort(anArray, new Comparator<int[]>() {
public int compare(int[] lhs, int[] rhs) {
return lhs[0]-rhs[0];
}
});
First of all, you need nested for loops in order to properly insert the random numbers into the two dimensional array. I have also updated my response to show how the sorting should be done. Hope this helps!
EDITED TO SATISFY REQUIREMENTS MENTIONED IN COMMENT BELOW.
import java.util.Arrays;
import java.util.Random;
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
int rows = 2;
int columns = 50;
int[][] anArray = new int[rows][columns];
Random rand = new Random();
//initialize the first row only
for (int j = 0; j < anArray[0].length; j++)
{
int n = rand.nextInt(100);
anArray[0][j] = n;
}
System.out.println("-----------Before the Sort----------------");
for (int i = 0; i < anArray.length; i++)
{
for (int j = 0; j < anArray[0].length; j++)
{
System.out.print(anArray[i][j] + ", "); //format any way you want
}
System.out.println(); //to make each row print on a new line.
}
anArray = mySort(anArray);
System.out.println("-----------After the Sort----------------");
for (int i = 0; i < anArray.length; i++)
{
for (int j = 0; j < anArray[0].length; j++)
{
System.out.print(anArray[i][j] + ", "); //format any way you want
}
System.out.println(); //to make each row print on a new line.
}
}
private static int[][] mySort(int[][] anArray) {
int [][] result = new int[anArray.length][anArray[0].length];
int thisRow[] = getRow(anArray, 0);
Arrays.sort(thisRow);
for(int j = 0; j < thisRow.length; j++){
result[0][j] = anArray[0][j];
result[1][j] = thisRow[j];
}
return result;
}
private static int[] getRow(int[][] anArray, int row) {
int thisRow[] = new int[anArray[row].length];
for(int j = 0; j < anArray[row].length; j++){
thisRow[j] = anArray[row][j];
}
return thisRow;
}
}
You can sort by considering the 2D array 1D. Let's consider a 3x4 array.
1st element's index is 0, 2nd is 1, 3rd is 2, 4th is 3, 5th is 4, etc.
General formula to convert from a 1D index to a 2D:
row_index = _1D_index % nRows;
col_index = _1D_index % nCols;
For example the 5th element has the 1D index of 4, to get the row: 4 % 3 = 1, to get the col, 4 % 4 = 0, so your element is at 1,0. What's the point of all this? Now you can just make a function
int GetAt(int index)
{
return array[index % nRows][index % nCols];
}
and something along the lines of:
void Swap(int index1, int index2)
{
int r1 = index1 % nRows;
int c1 = index1 % nCols;
int r2 = index2 % nRows;
int c2 = index2 % nCols;
int temp = array[r1][c1];
array[r1][c1] = array[r2][c2];
array[r2][c2] = temp;
}
And sort the array as if it was one dimensional :)