I am trying to solve this assignment but not able to figure out the logic on how to get the median here.
Question:- Find the median of a 2D-Matrix. (which is a Minesweeper game's result). Only horizontal and vertical values (1's) are counted. (Please click on the link for sample results).
Question
Solution:-
public static int findMedian2(int[][] matrix)
{
int size = 0;
for(int i = 0; i < matrix.length; i++)
{
for(int j = 0; j < matrix[i].length; j++)
{
if(matrix[i][j] == 1)
{
size++;
dfs(matrix, i, j);
}
}
}
return size;
}
private static void dfs(int[][] grid, int r, int c)
{
if(r < 0 || r >= grid.length || c < 0 || c >= grid[r].length || grid[r][c] == 0)
return;
grid[r][c] = 0;
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
So far I am able get the size. The size does not really give the right answer here, how do I achieve the median? I am new to matrix related problems. Any help would be greatly appreciated.
Update:-
Based on #Mike'Pomax'Kamermans's input I could come up with this:-
static int count;
static List<Integer> list = new ArrayList<Integer>();
public static int findMedian(int[][] matrix)
{
count = 0;
for (int i = 0; i < matrix.length; i++)
{
for (int j = 0; j < matrix[i].length; j++)
{
if (matrix[i][j] == 1)
{
dfs(matrix, i, j);
if (count != 0 && count != 1)
{
list.add(count);
}
count = 0;
}
}
}
// convert list to array
int[] array = list.stream().mapToInt(i -> i).toArray();
return findMedian(array);
}
private static void dfs(int[][] grid, int r, int c)
{
if(r < 0 || r >= grid.length || c < 0 || c >= grid[r].length || grid[r][c] == 0)
return;
grid[r][c] = 0;
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
count++;
}
/* Median of Unsorted Array to match the results */
private static int findMedian(int[] a)
{
// check for even case
if (a.length % 2 != 0)
{
return a[a.length / 2];
}
return (a[(a.length - 1) / 2] + a[a.length / 2]) / 2;
}
Will this be the correct way to calculate median for this question?
Related
I was doing a basic program of right rotation of array and for base condition, I wanted to exit the function with return. However, it is giving an error that type is not valid.
Can anyone explain why this is happening?
import java.util.*;
public class RightRotationArray{
public int[] solution(int[] A, int K) {
if (K < 0 || K >= A.length) {
return; // error showing here.
}
for (int i = 0; i < K; i++) {
int last = A[A.length - 1];
for (int j = A.length - 2; j >= 0; j--) {
A[j + 1] = A[j];
}
A[0] = last;
}
return A;
}
}
you can (return null) or (return new int[]{}), but the best way is to throw an exception:
public int[] solution(int[] A, int K) throws IllegalArgumentException{
if (K < 0 || K >= A.length) {
throw new IllegalArgumentException("K is invalid");
}
for (int i = 0; i < K; i++) {
int last = A[A.length - 1];
System.arraycopy(A, 0, A, 1, A.length - 2 + 1);
A[0] = last;
}
return A;
}
I got a homework assignment, I have to find a recursive function that gets a 2D matrix and the number of rows in a matrix and returns true / false If the diagonal of the matrix has a sequence of letters a b c,
Can not think of a solution
public static void main(String[] args) {
char[][] mat = new char[5][5];
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[i].length; j++)
mat[i][j] = (char) (int) ((Math.random() * 26) + 'a');
}
for (int i=0 ; i <mat.length ; i++)
mat[i][i] = (char)('a' + i);
//mat[2][2] = 'b';
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[i].length; j++)
System.out.print(mat[i][j] + " ");
System.out.println();
}
System.out.println(isDiagonalLettersSequence(mat, mat.length));
}[Here are two examples that I hope will help me explain myself][1]
https://i.stack.imgur.com/Z6qmn.png
This is pretty simple. Just check on each iteration if the current value is equals to previous +1:
public static boolean isDiagonalHasSequence(char[][] matrix) {
return isDiagonalHasSequence(matrix, 0);
}
private static boolean isDiagonalHasSequence(char[][] matrix, int row) {
if (row > 0 && row < matrix.length) {
// check diagonal \
if (matrix[row][row] != matrix[row - 1][row - 1] + 1)
return false;
// check diagonal /
if (matrix[row][matrix.length - row - 1] != matrix[row - 1][matrix.length - row - 2] + 1)
return false;
}
return row == matrix.length || isDiagonalHasSequence(matrix, row + 1);
}
In the main function:
String[][] arr = { {"a","e","d"},
{"h","b","c"},
{"f","f","c"}};
if(diagonal(arr, 0).equals("abc"))
System.out.print("true");
And the global recursive function should be:
public static String diagonal(String[][] arr, int i) {
if(i == arr.length - 1)
return arr[i][i];
return arr[i][i] + diagonal(arr, i + 1);
}
I am trying to find the expected output to the below program..But I am getting the error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at programbasics.CountingConnections.count(CountingConnections.java:7)
at programbasics.CountingConnections.main(CountingConnections.java:26)
My question is about a matrix m*n. The elements in matrix are populated with values 1 and 0.
1 indicates in establishing connection and 0 indicates Not establishing connection.
we need to connect the available adjacent positions vertically, horizontally and diagonally and count the number of distinct connections established
My piece of code is
package programbasics;
class CountingConnections
{
static int count(int a[][], int i, int j) {
int rows = a.length;
int cols = a[0].length;
if(a[i][j] == 0) return 0;
if (i == rows - 1 && j == cols - 1)
return a[i][j];
else if (i == rows - 1)
return a[i][j + 1];
else if (j == cols - 1)
return a[i + 1][j];
else if (a[i][j] == 1)
return count(a, i + 1, j) + count(a, i, j + 1);
else
return 0;
}
public static void main(String[]args)
{
int a[][] = {{1,0,0,1},
{0,1,1,1},
{1,0,0,1}};
int i = 3;
int j = 4;
System.out.println(count(a, i, j));;
}
}
The expected output is 8. Like the positions are connected as follows
1)(0,0) -> (1,1)
2)(2,0) -> (1,1)
.
.
.
.
8) (0,3) -> (1,3)
It fails to get the expected output 8.
public static int count(int[][] a) {
int[][] paths = new int[a.length][a[0].length];
if ((paths[0][0] = a[0][0]) == 0) {
return 0;
}
for (int c = 1; c < a[0].length; c++) {
paths[0][c] = a[0][c] * paths[0][c - 1];
}
for (int r = 1; r < a.length; r++)
{
paths[r][0] = a[r][0] * paths[r - 1][0];
for (int c = 1; c < a[r].length; c++)
{
paths[r][c] = a[r][c] * (paths[r - 1][c] + paths[r][c - 1]);
}
}
return paths[a.length - 1][a[0].length - 1];
}
public static int count(int[][] a, int m, int n) {
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] == 1) {
if (i - 1 >= 0 && j - 1 >= 0 && a[i - 1][j - 1] == 1) {
count = count + 1;
}
if (i - 1 >= 0 && a[i - 1][j] == 1) {
count = count + 1;
}
if (i - 1 >= 0 && j + 1 < n && a[i - 1][j + 1] == 1) {
count = count + 1;
}
if (j + 1 < n && a[i][j + 1] == 1) {
count = count + 1;
}
}
}
}
return count;
}
You call if(a[i][j] == 0) in your code where you pass 3 as i and 4 as j. However Array's are zero indexed, so when you try to call a[3][4] you are trying to call
0 1 2 3 4
0 {1, 0, 0, 1}
1 {0, 1, 1, 1}
2 {1, 0, 0, 1}
3 X
4
The index where the X is. Clearly this is not a valid index in your Array.
Also your method at different points calls a[i + 1][j] and a[i][j + 1] which means that you will have to take this in account when making sure the code stays in bounds.
As to your actual method your logic seems a bit off. if(a[i][j] == 0) return 0; will return 0 and stop the recursion and return 0 without checking to see if there are any more connections. Your logic should be something more like this:
Start at 0,1.
If the index is a 1
Look one index to the right, one down and to the right (The diagonal) down one, and down one and to the left (The second diagonal).
If any of the numbers at those index's are 1's then up the counter.
Continue to iterate through the matrix, but keep in mind that you are checking one row down and over, so you will only loop until less than length -1 for for both the row and column. Also make sure that you are starting at index a[i][1] as you will be needing to check a[a+1][j-1] and if j == 0 you will be trying to call a[a+1][-1] which will cause another index out of bounds
private int countConnections(int[][] a, int rows, int columns) {
//cartesian plane coordinates around a point
final int[] x = {1, 1, 1, -1, -1, -1, 0, 0};
final int[] y = {1, -1, 0, 1, -1, 0, 1, -1};
int count = 0;
boolean[][] visited = new boolean[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
for (int k = 0; k < 8; k++) {
int l = i + x[k];
int m = j + y[k];
//check for connections only if the given cell has value 1
if (a[i][j] == 1 && canVisit(l, m, rows, columns, visited) && a[l][m] == 1) {
count++;
}
}
visited[i][j] = true;
}
}
return count;
}
private boolean canVisit(int i, int j, int rows, int columns, boolean [][] visited) {
return i < rows && j < columns && i >= 0 && j >= 0 && !visited[i][j];
}
Check all the 8 cells around a cell whose cell value is 1 and when traversed mark it as visited.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have the below java method called solution, there are two large for loops, as you can see, the two for loops are very samilar, so I think it's possible to refactor the code by having a method like public int getElementSize(ArrayList<Integer> factor1, ArrayList<Integer> factor2) which does the work of the for loop, so I can just call the method twice with different parameters instead repeating the two for loop. But since these two for loops have different loop orders, one from head to tail, another one from tail to head, beside this, all other parts of the loop are the same, any ideas how to refactor this code?
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
return 0;
}
}
How about this?
Conditional operator, ? and : similar to, (these are called ternary operators and resolve at compile time to if else blocks)
if(condition) {
this();
} else {
that();
}
In the above, you can single line that as, (condition ? this() : that())
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
// let i = 0 to be factor2, i = 1 is factor 1
for(int i = 0; i < 2; i++) {
for(int x = (i == 0 ? 1 : factor1.size() - 1); (i == 0 ? x < factor2.size() : x >= 0); (i == 0 ? x++ : x--)){
int blockSize = (i == 0 ? factor2.get(x) : factor1.get(x));
int elementSize = (i == 0 ? factor1.get(x) : factor2.get(x));
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
}
return 0;
}
}
You can refactor the code inside the the for loops to the new method inside move the two big for loops to the new method, in this way, the order of the two loops are still independent, basically it looks like below, the correctness needs to be verified, this is just one idea to not repeat:
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
return 0;
}
//this method include the code which was repeated inside the loops
public int getElementSize(int[] A, int blockSize, int elementSize){
int peaks = 0;
int N = A.length;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
return peaks;
}
}
I have a 3x4 matrix represented by a 2D array:
. 0 1 2 3
0 a c f i
1 b e h k
2 d g j l
and my approach to traverse the diagonal slice was to treat each slice as a sum, like this:
a = (0+0) = 0
b,c = (0+1),(1+0) = 1
d,e,f = (0+2),(1+1),(2+0) = 2
g,h,i = (1+2),(2+1),(3+0) = 3
j, k = (2+2),(3+1) = 4
l = (3+2) = 5
However, my code right now prints it in the opposite way that I want it to, which is from upper right to bottom left.
Current Output is:
acbfedihgkjl
Desired Output is:
abcdefghijkl
for (int sum = 0; sum <= numRows + numColumns - 2; sum++) {
for (int i = 0; i < numRows; i++) {
int j = sum - i;
if ((i >= 0 && i < numRows) && (j >= 0 && j < numColumns)) {
System.out.print(array[i][j]);
}
}
}
Can somebody point me in the right direction on how to fix my code to get the output that I want?
While it isn't very pretty, I think this will do it:
int i = 0;
int j = 0;
while (true) {
System.out.println("" + array[i][j]);
--i;
++j;
if (i < 0) {
if (j == numCols)
break;
i = Math.min(j, numRows - 1);
j = Math.max(j - numCols + 2, 0);
} else if (j >= numCols) {
if (i == numRows - 2)
break;
i = numRows - 1;
j = Math.max(j + 2 - numCols + i, 0);
}
}
int i = 0;
int j = 0;
int n = 0;
int x = 3;
int y = 4;
int newSize = Math.max(x,y) * Math.max(x,y);
while(n < newSize){
if(i <= x && j <= y)
System.out.println(array[i][j]);
n++;
if(i == 0) {
i = n:
j = 0;
} else {
--i;
++j;
}
}