Count number of ones in a matrix in increasing order - java

I have this island program that just displays the number of possible islands in a matrix.
I have a matrix of 1's and 0's I want to get group of 1's in row wise, column wise and diagonal wise. This program count the number of possibilities and returns 5 as output for below input.
{ 1, 0, 0, 1, 0 },
{ 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 1 }
But I need output as island sizes in increasing order as 1 2 2 4
How to achieve this?
Explanation: a) last row first column has single island, b) first row 1st column, 2nd row 1st column and has island of size 2. c) 3rd row last column, last row last column has island of size 2. d) 1st row 4th column, remaining rows 3rd column has size of 4.
public class Islands {
// No of rows and columns
static final int ROW = 4, COL = 5;
// A function to check if a given cell (row, col) can
// be included in DFS
static boolean isSafe(int M[][], int row, int col, boolean visited[][]) {
// row number is in range, column number is in range
// and value is 1 and not yet visited
return (row >= 0) && (row < ROW) && (col >= 0) && (col < COL) && (M[row][col] == 1 && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix.
// It only considers the 8 neighbors as adjacent vertices
static void DFS(int M[][], int row, int col, boolean visited[][]) {
// These arrays are used to get row and column numbers
// of 8 neighbors of a given cell
int rowNbr[] = new int[] { -1, -1, -1, 0, 0, 1, 1, 1 };
int colNbr[] = new int[] { -1, 0, 1, -1, 1, -1, 0, 1 };
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited))
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns count of islands in a given
// boolean 2D matrix
static int countIslands(int M[][]) {
// Make a bool array to mark visited cells.
// Initially all cells are unvisited
boolean visited[][] = new boolean[ROW][COL];
// Initialize count as 0 and travese through the all cells
// of given matrix
int count = 0;
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] == 1 && !visited[i][j]) // If a cell with
{ // value 1 is not
// visited yet, then new island found, Visit all
// cells in this island and increment island count
DFS(M, i, j, visited);
++count;
}
return count;
}
// Driver method
public static void main(String[] args) throws java.lang.Exception {
int M[][] = new int[][] { { 1, 0, 0, 1, 0 }, { 1, 0, 1, 0, 0 }, { 0, 0, 1, 0, 1 }, { 1, 0, 1, 0, 1 } };
System.out.println("Number of islands is: " + countIslands(M));
}
}

Make following changes to solve it:
Add static variable size to count size for each island.
Replace count by listSizes to store the size of each island. New island's size is added to this list.
Invoke the method (renamed from countIslands to sizeIslands) to get final listSizes.
Sort the list before printing it out.
Final code:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Islands {
// No of rows and columns
static final int ROW = 4, COL = 5;
static int size;
// A function to check if a given cell (row, col) can
// be included in DFS
static boolean isSafe(int M[][], int row, int col, boolean visited[][]) {
// row number is in range, column number is in range
// and value is 1 and not yet visited
return (row >= 0) && (row < ROW) && (col >= 0) && (col < COL) && (M[row][col] == 1 && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix.
// It only considers the 8 neighbors as adjacent vertices
static void DFS(int M[][], int row, int col, boolean visited[][]) {
// These arrays are used to get row and column numbers
// of 8 neighbors of a given cell
int rowNbr[] = new int[] { -1, -1, -1, 0, 0, 1, 1, 1 };
int colNbr[] = new int[] { -1, 0, 1, -1, 1, -1, 0, 1 };
// Mark this cell as visited
visited[row][col] = true;
size++;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited))
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns size of islands in a given
// boolean 2D matrix
static List<Integer> sizeIslands(int M[][]) {
// Make a bool array to mark visited cells.
// Initially all cells are unvisited
boolean visited[][] = new boolean[ROW][COL];
// Initialize empty list and travese through the all cells
// of given matrix
List<Integer> listSizes = new ArrayList<Integer>();
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] == 1 && !visited[i][j]) // If a cell with
{ // value 1 is not
// visited yet, then new island found, Visit all
// cells in this island and increment island count
size = 0;
DFS(M, i, j, visited);
listSizes.add(size);
}
return listSizes;
}
// Driver method
public static void main(String[] args) throws java.lang.Exception {
int M[][] = new int[][] { { 1, 0, 0, 1, 0 }, { 1, 0, 1, 0, 0 }, { 0, 0, 1, 0, 1 }, { 1, 0, 1, 0, 1 } };
List<Integer> list = sizeIslands(M);
Collections.sort(list);
System.out.println("Sizes of islands are: " + list);
}

Related

How would I make an entire row in an array one value in Java?

How would I make an entire row (or column) one value in an array? For example, I have a row of all random numbers, and I want to set all of these values to 0.
Here is what I have so far:
public class Assignment12 {
public static void main(String args[]) {
int[][] timestable = new int[10][10];
printSquare(timestable);
zeroRow(timestable, 5);
printSquare(timestable);
int[] arr = timestable[0];
}
public static void printSquare(int[][] arr) {
for (int row = 0; row < 10; row++)
for (int col = 0; col < 10; col++)
arr[row][col] = (row + 1) * (col + 1);
System.out.println();
for (int row = 0; row < 10; row++) {
for (int col = 0; col < arr.length; col++)
System.out.printf("%4d", arr[row][col]);
System.out.println();
}
}
public static void zeroRow(int[][] arr, int M) {
for (int col = 0; col < M; col++) {
if (arr[M][col] != 0) {
arr[M][col] = 0;
}
}
}
}
Arrays of primitives are filled with default values (0 for integer types, 0.0/0.0f for floating-point types, false for boolean) and null for objects upon creation.
To populate a single row in a 2D array, it's recommended to use Arrays.fill method:
public static void fillRow(int[][] arr, int row, int value) {
if (row < arr.length && row >= 0 && null != arr[row]) {
Arrays.fill(arr[row], value);
}
}
public static void zeroRow(int[][] arr, int row) {
fillRow(arr, row, 0);
}
Specific columns can be filled using loops:
public static void fillColumn(int[][] arr, int col, int value) {
for (int[] row : arr) {
if (null != row && col >= 0 && col < row.length) {
row[col] = value;
}
}
}
public static void zeroColumn(int[][] arr, int col) {
fillColumn(arr, col, 0);
}
How would I make an entire row in an array one value in Java?
By default, primitive int arrays of a fixed length are initialized to 0's. To fill them with other values you can do the following.
Use the Arrays.fillmethod.
int[] tens = new int[5];
Arrays.fill(tens,10);
System.out.println(Arrays.toString(tens));
Prints
[10, 10, 10, 10, 10]
Or you can write a lambda and call it when you need to fill an array. It will also create the array for you since you supply the length.
BiFunction<Integer, Integer, int[]> fill =
(val, len) -> {
int[] temp = new int[len];
Arrays.fill(temp, val);
return temp;};
int[] twos = fill.apply(2,10);
int[] threes = fill.apply(3,4);
System.out.println(Arrays.toString(twos));
System.out.println(Arrays.toString(threes));
prints
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
[3, 3, 3, 3]
Or, in a pinch, generate one from an IntStream. For an array of 5's with length of 7 do the following:
int[] fives = IntStream.generate(()-> 5).limit(7).toArray();
Note: Once you have your linear array you can also assign it to any row in a 2D array. Consider the previous examples of twos and threes.
int[][] b = new int[2][];
b[0] = twos;
b[1] = threes;
You can process an array as follows:
public static void fillRow(int[][] arr, int row, int val) {
Arrays.fill(arr[row], val);
}
public static void fillColumn(int[][] arr, int column, int val) {
Arrays.stream(arr).forEach(row -> row[column] = val);
}
public static void main(String[] args) {
int[][] arr = new int[5][5];
fillRow(arr, 3, 3);
fillColumn(arr, 2, 2);
// output
Arrays.stream(arr).map(Arrays::toString).forEach(System.out::println);
}
[0, 0, 2, 0, 0]
[0, 0, 2, 0, 0]
[0, 0, 2, 0, 0]
[3, 3, 2, 3, 3]
[0, 0, 2, 0, 0]

Sudoku Solver Not Solving Correctly

I have created a program that takes in a test case unfinished Sudoku puzzle and is supposed to use multi-threading to quickly solve it. I have run into a problem where it only works 1/3 times, and when it does "work", it returns a puzzle that breaks rules. Such as, two fives in the same column. I am wondering if the threads are acting too fast and not communicating? What are things I can change or problems I am not seeing?
Here is my SudokuSolver class. It contains two methods: cellChecker and fillPuzzle. The cell checker checks individual cells and returns false when their filled or true if the cell is empty (contains a 0). It also contains the code for the multi-threading, where I suspect the problem is.
fillPuzzle simply creates the puzzle if needed, and uses cellChecker to correctly solve the sudoku puzzle.
public boolean cellChecker(int puzzle[][], int row, int col, int number) {
//Set the cellCheck boolean to true for a default case
cellCheck = true;
//variables that give us the start of the row and column respectively
//If it doesn't get divided by 3 and then multiplied by 3, the threads
//get an out of bounds exception and gets real mad. found this math
//from stackoverflow.
int rowStart = (row / 3) * 3;
int colStart = (col / 3) * 3;
//The threads are created to do the 9x9 grid in 3x3 sections,
//so it can get done quicker and cut down the large task at hand.
//checks via col
Thread thread1 = new Thread(new Runnable() {
public void run() {
//for loop that checks the col
for (int i = 0; i < 9; i++) {
if (puzzle[row][i] == number) {
cellCheck = false;
}
}
}
});
thread1.start();
//another thread to take on it's 3x3 part via row
Thread thread2 = new Thread(new Runnable() {
public void run() {
//for loop that checks the row
for (int i = 0; i < 9; i++) {
if (puzzle[i][col] == number) {
cellCheck = false;
}
}
}
});
thread2.start();
//another thread to take on it's 3x3 part via cell by cell
Thread thread3 = new Thread(new Runnable() {
public void run() {
//for loop that checks the specific cell
for (int rowCell = rowStart; rowCell < rowStart + 3; rowCell++) {
for (int colCell = 0; colCell < colStart + 3; colCell++) {
if (puzzle[rowCell][colCell] == number) {
cellCheck = false;
}
}
}
}
});
thread3.start();
//returns the boolean whether the box is empty or not. If it is false,
//it is filled with the number it needs. if it's true, it still needs
//a number
return cellCheck;
}
public boolean fillPuzzle(int puzzle[][], int row, int col) {
if (row < 9) {
//if the 9x9 puzzle is not created and filled with 0's, create it
if (puzzle[row][col] != 0) {
if (col < 8) {
//returns created 9x9 puzzle
return fillPuzzle(puzzle, row, col + 1);
} else if (row < 8) {
//returns created 9x9 puzzle
return fillPuzzle(puzzle, row + 1, 0);
}
//already created, return true!
return true;
} else {
//if the puzzle is created, go through and check for the number
//up until or equal to 9 because sudoku goes from 1-9
//once it finds the number that belongs in the cell, it
//puts it in that cell
for (int i = 1; i <= 9; i++) {
if (cellChecker(puzzle, row, col, i)) {
puzzle[row][col] = i;
//If at the end of col, add a row to finish the table
if (col == 8) {
if (fillPuzzle(puzzle, row + 1, 0)) {
return true;
}
} else {
//add 1 to the col if it doesn't == 8 because
//that means there's not enough cols
if (fillPuzzle(puzzle, row, col + 1)) {
return true;
}
}
//all else fails, set it to 0 and we'll check it later
puzzle[row][col] = 0;
}
}
return false;
}
}
return true;
}
and this is my menu class where the puzzle test case occurs
public class Menu {
private SudokuSolver solver = new SudokuSolver();
//This is a test case sudoku puzzle I found off the internet to use as
//an example
private int sudokuPuzzle[][] = {{8, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}};
public void start() {
//set to the method fillPuzzle. It tries to solve the
//sudoku puzzle and if it does, it is set to true. If it doesn't
//it says no thank you.
boolean filledPuzzle = solver.fillPuzzle(sudokuPuzzle, 0, 0);
//if it filled the puzzle, it prints it out.
if (filledPuzzle) {
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
System.out.print(sudokuPuzzle[row][col] + " ");
}
System.out.println();
}
//if it can't, it let's the person know.
} else {
System.out.println("Solution not found");
}
}
}
Finally, this may sound dumb but I'm not 100% sure how implements Runnable works, but it did give me an empty run method in my sudokusolver class and gets angry if I remove it. I was wondering if something needs to be put there for it to work correctly and efficiently?
#Override
public void run() {
}

how to check all reachable cells from one cell

I need to check all possible paths that is reachable from one certain cell in a 2d array. For example;
int [][] grid = {{2, 0, 0, 1, 1, 2},
{1, 0, 2, 0, 0, 1},
{1, 0, 2, 0, 4, 2},
{8, 3, 4, 0, 1, 2},
{1, 2, 5, 0, 3, 3},
{5, 1, 1, 2, 1, 0}};`
and I want to check all cells that is reachable from cell(2)(1) (it is just an example location). First some number will be placed here if this location is zero. For example, 1 is placed at that location.
Then I need to start merging all 1’s which are reachable from cell (2,1).Then cell(2)(1) location must be replaced with the 2 if the cells that create this path includes at least two 1 since 1+1 = 2.
After that, the cells which are used during merging process must be assigned to zero.
But if there is still possible merging for cell(2)(1) they should be merged too.
I try to use recursive function but it did not work as I want.
I could not figure out how to prevent merging if there are less than 3 neighbor cells which includes same value and how to merge until no possible merging left. Method should continue merging until there are no possible merge left, but my code merge for once. I have just started to learn java sorry for mistakes already now.
So...
I am not sure if I got everything right because some things are misleading.
cell(2)(2) has the initial content: 2
I think your chosen cell is (1)(2). //note: indices in java start with 0
So your idea is a little bit more complex and should not be solved with only one method.
I've written some code:
private static int[][] directions = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
public static void step(int[][] array, int x, int y) {
if(array[x][y] == 0){
array[x][y] = 1;
}else{
return;
}
int number = 1;
while(true){
printGrid(array);
int amount = process(array, x, y);
if(amount == 1)break;
number ++;
array[x][y] = number;
}
}
public static int process(int[][] array,int x, int y){
int number = array[x][y];
if(number == 0) return 0;
int total = 1;
array[x][y] = 0;
for(int[] dire:directions){
if(x + dire[0] >= 0 && x + dire[0] < array.length && y + dire[1] >= 0 && y + dire[1] < array[0].length){
if(array[x + dire[0]][y+dire[1]] == number){
total += process(array, x + dire[0], y+dire[1]);
}
}
}
return total;
}
public static void printGrid(int[][] grid) {
for(int i = 0; i < grid.length; i++){
String s = "";
for(int n = 0; n< grid[0].length; n++){
s += grid[i][n]+", ";
}
System.out.println(s);
}
System.out.println("");
}
public static void main(String[] args){
int [][] grid =
{{2, 0, 0, 1, 1, 2},
{1, 0, 2, 0, 0, 1},
{1, 0, 2, 0, 4, 2},
{8, 3, 4, 0, 1, 2},
{1, 2, 5, 0, 3, 3},
{5, 1, 1, 2, 1, 0}};
Main.step(grid, 2,1);
printGrid(grid);
}
I modified it like this;
public static void main(String []args){
System.out.println("Welcome to the game Merge Numbers. Your grid as follows:");
int[][] newGrid = {{2, 0, 1, 1, 0, 8},
{2, 1, 0, 2, 4, 0},
{1, 2, 1, 2, 1, 3},
{2, 3, 2,0, 1, 0},
{0, 0, 5, 8, 7, 2},
{2, 0, 1, 1, 0, 0}};
for(int i = 0 ; i < newGrid.length ; i++){
for (int j = 0; j < newGrid[i].length; j++) {
System.out.print(newGrid[i][j] + " ");
}
System.out.println();
}
try (Scanner keyboard = new Scanner(System.in)){
System.out.print("Please enter your target's row index:");
int newRow = keyboard.nextInt();
System.out.print("Please enter your target's column index:");
int newColumn = keyboard.nextInt();
System.out.print("Please enter the number that you want to add to location " + newRow + " " + newColumn);
int newNextNumber = keyboard.nextInt();
step(newGrid, newRow, newColumn, newNextNumber);
for(int i = 0 ; i < newGrid.length ; i++){
for (int j = 0; j < newGrid[i].length; j++) {
System.out.print(newGrid[i][j] + " ");
}
System.out.println();
}}
}
public static void step(int[][] grid, int row, int column, int nextNumber ) {
if(grid[row][column] == 0){
grid[row][column] = nextNumber;
}else{
return;
}
int number = nextNumber;
while(true){
int amount = process(grid, row, column);
if(amount == 1)break;
number ++;
grid[row][column] = number;
}
}
public static int process(int[][] grid,int row, int column){
int number = grid[row][column];
if(number == 0) return 0;
int total = 1;
grid[row][column] = 0;
for(int[] dire:directions){
if(row + dire[0] >= 0 && row + dire[0] < grid.length && column + dire[1] >= 0 && column + dire[1] < grid[0].length){
if(grid[row + dire[0]][column+dire[1]] == number){
total += process(grid, row + dire[0], column+dire[1]);
}
}
}
return total;
}
}
But when I run it all the points include the target location becomes zero. Output is like;
Welcome to the game Merge Numbers. Your grid as follows:
2 0 1 1 0 8
2 1 0 2 4 0
1 2 1 2 1 3
2 3 2 0 1 0
0 0 5 8 7 2
2 0 1 1 0 0
Please enter your target's row index:3
Please enter your target's column index:3
Please enter the number that you want to add to location 3 3: 1
2 0 1 1 0 8
2 1 0 0 4 0
1 2 1 0 0 3
2 3 0 0 0 0
0 0 5 8 7 2
2 0 1 1 0 0
I mean if you look at the first grid in the output, cell(3)(3) is zero. When 1 is placed here, the 1's that are reachable from this cell(3)(3) merged. Then cell(3)(3) includes 2. After that same procedure follows. But when all possible merges done, all cells that has been used during the process include center became 0. Center should be increase by one after each merging. I think, I use the fourth parameter which is nextNumber incorrectly. Should function process also include that parameter or not? Sorry to disturb you so much :)
here is how you can find neighbors of a cell...
int x[] = {-1, -1, -1, 0, 0, +1, +1, +1};
int y[] = {-1, 0, +1, -1, +1, -1, 0, +1};
// looping through the neghibours...
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
// neighbour
}
}
Here is the recursive implementation of your problem, n & m is the size of grid a and p & q is the index of the cell you want to perform merge...
public static void merge(int a[][], int n, int m, int p, int q) {
int x[] = {-1, -1, -1, 0, 0, +1, +1, +1};
int y[] = {-1, 0, +1, -1, +1, -1, 0, +1};
int c = 0;
// looping through the neghibours...
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
c++;
}
}
if(c > 3) { // merging only if neghibours > 3
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
a[p + x[i]][q + y[i]] = 0;
}
}
a[p][q] += 1;
merge(a, n, m, p, q); // recurcively merging if possible...
}
}

Optimize code for Nth largest element in sorted matrix

I have a code for nth largest element in a sorted matrix (sorted row and column wise increasing order)
I had some problem doing the (findNextElement) part in the code
i.e if the row is exhausted, then go up one row and get the next element in that.
I have managed to do that, but the code looks kind of complex. (My code does work and produces the output correctly) I will post my code here
k is the Kth largest element
m, n are matrix dimensions (right now it just supports NxN matrix but can be modified to support MxN)
public int findkthLargestElement(int[][] input, int k, int m, int n) {
if (m <=1 || n <= 1 || k > m * n) {
return Integer.MIN_VALUE;
}
int i = 0;
int j = 0;
if (k < m && k < n) {
i = m - k;
j = n - k;
}
PriorityQueue<Element> maxQueue = new PriorityQueue(m, new Comparator<Element>() {
#Override
public int compare(Element a, Element b) {
return b.value - a.value;
}
});
Map<Integer, Integer> colMap = new HashMap<Integer, Integer>();
for (int row = i; row < m; row++) {
Element e = new Element(input[row][n - 1], row, n - 1);
colMap.put(row, n - 1);
maxQueue.add(e);
}
Element largest = new Element(0, 0, 0);
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
while (col < j && row > i) {
row = row - 1;
colMap.put(row, colMap.get(row) - 1);
col = Math.max(0, colMap.get(row));
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
return largest.value;
}
I need some help in the for loop specifically, please suggest me a better way to accomplish the task.
I have my code running here
http://ideone.com/wIeZSo
Ok I found a a simple and effective way to make this work, I changed my for loop to ths
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
if (col < j) {
continue;
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
If we are exhausted with a column then we do not add anymore items till we reach an element from some other column.
This will also work for matrix which are only sorted row wise but not column wise.
In response to the comment: Even if there are duplicate elements, I don't think that it is necessary to use sophisticated data structures like priority queues and maps, or even inner classes. I think it should be possible to simply start at the end of the array, walk to the beginning of the array, and count how often the value changed. Starting with the value "infinity" (or Integer.MAX_VALUE here), after the kth value change, one has the kth largest element.
public class KthLargestElementTest
{
public static void main (String[] args) throws java.lang.Exception
{
testDistinct();
testNonDistinct();
testAllEqual();
}
private static void testDistinct()
{
System.out.println("testDistinct");
int[][] input = new int[][]
{
{1, 2, 3, 4},
{8, 9, 10, 11},
{33, 44, 55, 66},
{99, 150, 170, 200}
};
for (int i = 1; i <= 17; i ++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testNonDistinct()
{
System.out.println("testNonDistinct");
int[][] input = new int[][]
{
{ 1, 1, 1, 4 },
{ 4, 4, 11, 11 },
{ 11, 11, 66, 66 },
{ 66, 150, 150, 150 }
};
for (int i = 1; i <= 6; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testAllEqual()
{
System.out.println("testAllEqual");
int[][] input = new int[][]
{
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 }
};
for (int i = 1; i <= 2; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
public static int findkthLargestElement(
int[][] input, int k, int m, int n)
{
int counter = 0;
int i=m*n-1;
int previousValue = Integer.MAX_VALUE;
while (i >= 0)
{
int value = input[i/n][i%n];
if (value < previousValue)
{
counter++;
}
if (counter == k)
{
return value;
}
previousValue = value;
i--;
}
if (counter == k)
{
return input[0][0];
}
System.out.println("There are no "+k+" different values!");
return Integer.MAX_VALUE;
}
}

Depth first search bug?

So I have a matrix of N×M. At a given position I have a value which represents a color. If there is nothing at that point the value is -1. What I need to do is after I add a new point, to check all his neighbours with the same color value and if there are more than 2, set them all to -1.
If what I said doesn't make sense what I'm trying to do is an algorithm which I use to destroy all the same color bubbles from my screen, where the bubbles are memorized in a matrix where -1 means no bubble and {0,1,2,...} represent that there is a bubble with a specific color.
Also, if you have any suggestions I'd be grateful. Thanks.
This is what I tried and failed:
public class Testing {
static private int[][] gameMatrix=
{{3, 3, 4, 1, 1, 2, 2, 2, 0, 0},
{1, 4, 1, 4, 2, 2, 1, 3, 0, 0},
{2, 2, 4, 4, 3, 1, 2, 4, 0, 0},
{0, 4, 2, 3, 4, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
static int Rows=6;
static int Cols=10;
static int count;
static boolean[][] visited=new boolean[15][15];
static int NOCOLOR = -1;
static int color = 1;
public static void dfs(int r, int c, int color, boolean set)
{
for(int dr = -1; dr <= 1; dr++)
for(int dc = -1; dc <= 1; dc++)
if(!(dr == 0 && dc == 0) && ok(r+dr, c+dc))
{
int nr = r+dr;
int nc = c+dc;
// if it is the same color and we haven't visited this location before
if(gameMatrix[nr][nc] == color && !visited[nr][nc])
{
visited[nr][nc] = true;
count++;
dfs(nr, nc, color, set);
if(set)
{
gameMatrix[nr][nc] = NOCOLOR;
}
}
}
}
static boolean ok(int r, int c)
{
return r >= 0 && r < Rows && c >= 0 && c < Cols;
}
static void showMatrix(){
for(int i = 0; i < gameMatrix.length; i++) {
System.out.print("[");
for(int j = 0; j < gameMatrix[0].length; j++) {
System.out.print(" " + gameMatrix[i][j]);
}
System.out.println(" ]");
}
System.out.println();
}
static void putValue(int value,int row,int col){
gameMatrix[row][col]=value;
}
public static void main(String[] args){
System.out.println("Initial Matrix:");
putValue(1, 4, 1);
putValue(1, 5, 1);
putValue(1, 4, 2);
showMatrix();
for(int n = 0; n < Rows; n++)
for(int m = 0; m < Cols; m++)
visited[n][m] = false;
//reset count
count = 0;
dfs(5,1,color,false);
//if there are more than 2 set the color to NOCOLOR
for(int n = 0; n < Rows; n++)
for(int m = 0; m < Cols; m++)
visited[n][m] = false;
if(count > 2)
{
dfs(5,1,color,true);
}
System.out.println("Matrix after dfs:");
showMatrix();
}
}
One issue you are encountering is that you do not check the upper row and leftest col:
static boolean ok(int r, int c)
{
return r > 0 && r < Rows && c > 0 && c < Cols;
}
you should check for r >= 0, c>= 0
Second issue is you are using dfs() twice, but the visited field is static - it is all set to true before the second run of dfs() you need to initialize it back to false in all fields before the second run, or the algorithm will terminate instantly without doing anything [since all the nodes are already in visited - and the algorithm will decide not to re-explore these nodes.].
Your code counts diagonal cells as neighbours too. If you want only left/right/top/bottom cells than you can check
if(!(dr == 0 && dc == 0) && ok(r+dr, c+dc) && dr * dc == 0)
You also need to count first cell. You don't count cell you start from.
I think you are after a flood-fill algorithm (perhaps with the slightly odd constraint that there must be at least two neighbours of the same colour)? I'm not sure why depth-first-search is appropriate here.

Categories

Resources