I am trying to solve this problem with recursion.
The problem is: for a two dimensional array of positive integers how can I return the longest path (steps), so that the value in each cell of the longest path is from descending series of integers and the difference between each cell and cell is a given number (num).
Assumes that n is a value of the cell so (n - num) is a positive number (not zero).
I can't use any loops (for,while,...etc)
the Method:
public static int longestPath(int matrix[][],int number){...
return(__overloading__);
}
For example:
int number=1;
int [][]matrix ;
matrix = new int[][]{{8, 15, 20, 33, 35},
{60, 59, 58, 32, 31},
{59, 17, 57, 56, 55},
{55, 15, 13, 58, 16}};
System.out.print(" longestPath= "+ longestPath(matrix, num));
}
if we search for the longest path with the difference number = 1
1-in the cell matrix[0][3] the path long is 3 and the value in this path is 33 -> 32 -> 31 ends in matrix[1][4]
2-in the cell matrix[1][0] the path long is for 6 and the value in the path 60 -> 59 -> 58 -> 57 -> 56 -> 55 ends in matrix[2][4]
3-in the cell matrix[1][0] the path long is 2 and the value in this path is 60 -> 59 ends in matrix[2][0]
so the method must return the longest path witch its 6
if we search for the longest path with the difference number = 2
1-in the cell matrix[2][1] the path long is 3 and the value in this path is 17 -> 15 -> 13 ends in matrix[3][2]
the method must return the longest path witch its 3.
My non-working code:
public class CC {
public static int longestPath (int arr[][] , int num){
return longestPath(arr,arr.length-1,arr[0].length-1,num,0);
}
public static int longestPath (int arr[][],int rows,int cols,int num,int max){
System.out.println("==> longestPath() arr value=" + arr[rows][cols] + " rows:"+rows + " cols:"+cols + " max:"+max);
if (cols ==0 && rows != 0 ){
cols = arr[0].length-1;
rows--;
}
if (rows ==0 && cols==0 ){
System.out.println("finish");
return 0;
}
int steps = searchPath(arr,rows,cols,num,max);
if (steps > max) max=steps;
longestPath(arr,rows,cols-1,num,max);
return max ;
}
public static int searchPath(int arr[][],int rows,int cols,int num ,int counter){
System.out.println("searchPath() arr value=" + arr[rows][cols] + " rows:"+rows + " cols:"+cols);
int left=1,right=1,up=1,down=1;
if ((cols != 0) && arr[rows][cols] - num == arr[rows-1][cols] ){ // checking up cell
counter++;
up = searchPath(arr,rows-1,cols,num,counter);
}
if ((rows != arr.length-1) && arr[rows][cols] - num == arr[rows+1][cols] ){ // checking down cell
counter++;
down = searchPath(arr,rows+1,cols,num,counter);
// return counter;
}
if ((cols != 0) && arr[rows][cols] - num == arr[rows][cols-1]){ // checking left cell
counter++;
left = searchPath(arr,rows,cols-1,num,counter);
//return counter;
}
if ((cols != arr[0].length-1) && arr[rows][cols] - num == arr[rows][cols+1] ){ //checking right cell
counter++;
right = searchPath(arr,rows,cols+1,num ,counter);
//return counter;
}
if ((left > right) && (left > up) && (left > down)) // if left cell is bigger than all other direction return left
return left;
if ((right > left) && (right > up) && (right > down))
return right;
if ((down > up) && (down > right) &&( down > left))
return down;
if ((up> down) && (up > right) && (up>left))
return up;
return 0;
}
}
While writing the code, I ran into a lot of running problems
what i'm doing wrong? thanks in advance
In the posted solution (as well as in the question) you iterate over entire two-dimensional array, starting at the top-left (0,0), and want to check neighbors for each element.
To check all neighbors, it is enough to check right and down neighbors to cover all1:
1: If you are interested in descending paths going up or left, you need to check 4 directions. This is because your graph is directed. For example, a path which may not be valid going left to right, may be valid going right to left.
By doing so, you simplify the code, and reduce duplicate testing of neighbors.
Another technique which makes code easier to read, debug and maintain, is breaking it into small well defined simple methods, for example:
private static boolean isValidAddress(int row, int col, int maxRow, int maxCol) {
if(row < 0 || col < 0) return false;
if(row >= maxRow || col >= maxCol) return false;
return true;
}
Try the following solution:
public class Main {
//moving in two directions, right and down, is sufficient
//to cover a whole matrix without visiting the same address twice
public static void main(String[] args) {
int delta= 1;
int [][]matrix = new int[][]{
{8, 15, 20, 33, 35},
{60, 59, 58, 32, 31},
{59, 17, 57, 56, 55},
{55, 15, 13, 58, 16}};
System.out.print(" longest Path= "+ longestPath(matrix, delta));
}
public static int longestPath (int arr[][] , int delta){
return longestPath(arr, 0, 0, delta , 0);
}
//check all matrix elements, keep longest path found
public static int longestPath (int arr[][],int row,int col, int num, int max){
int steps = searchPath(arr,row,col,num, 1); //Initial path length is always 1
if (steps > max) { max=steps; }
if (row == arr.length-1 && col == arr[row].length -1 ) return max;
col ++;
if(col == arr[row].length){//end of row exceeded
row++; //new row
col = 0; //first column
}
return longestPath(arr,row,col,num,max);
}
public static int searchPath(int arr[][],int row,int col,int num ,int pathLength){
int[][] neighbors = getNeighbors(arr, row, col, num);
int rightPath = 0 , downPath = 0;
//right neighbor
if(neighbors[0] != null){
rightPath = searchPath(arr, neighbors[0][0], neighbors[0][1], num, pathLength+1);
}
//down neighbor
if(neighbors[1] != null){
downPath = searchPath(arr, neighbors[1][0], neighbors[1][1], num, pathLength+1);
}
int returnPath = Math.max(rightPath, downPath); //max return value
return Math.max(pathLength, returnPath) ; //max of path length and returned value
}
//return neighbors with value smaller by delta
//returned array[0] represents right neighbor row, col or null
//returned array[1] represents down neighbor row, col or null
private static int[][] getNeighbors(int[][] arr, int row, int col, int delta) {
//moving in two directions, right and down, is sufficient
//to cover a whole matrix without visiting the same address twice
int[][] neighbors = {null, null};
//right neighbor
int newCol = col +1;
if(isValidAddress(row, newCol, arr.length, arr[0].length)){
if(arr[row][col] - arr[row][newCol] == delta){
neighbors[0] = new int[]{row, newCol};
}
}
//down neighbor
int newRow = row + 1 ;
if(isValidAddress(newRow, col, arr.length, arr[0].length)){
if(arr[row][col] - arr[newRow][col] == delta){
neighbors[1] = new int[]{newRow, col};
}
}
return neighbors;
}
private static boolean isValidAddress(int row, int col, int maxRow, int maxCol) {
if(row < 0 || col < 0) return false;
if(row >= maxRow || col >= maxCol) return false;
return true;
}
}