Messed up recursion code for a board game - java

What I have to do here is to count the number of adjacent white blocks (in 2's) on a square board which is made up of random black(0's) and white(1's) blocks. The white blocks have to be at i+1,j || i-1,j || i,j+1 || i,j-1. Technically diagonals are not counted. I have provided an example below:
[1 0 1]
[1 1 0]
[0 1 0]
Here count == 3 (0,0)(1,0) and (1,0)(1,1) and (1,1)(2,1)
Here is my code:
public int count = 0;
boolean count(int x, int y, int[][] mat)
{
if(x<0 || y<0)
return false;
if(mat[x][y] == 0)
return false;
for(int i = x; i<mat.length; i++)
{
for(int j = y; j<mat[0].length; j++)
{
if(mat[i][j] == 1)
{
mat[i][j] = 0;
if(count(i-1,j,mat))
count++;
if(count(i,j-1,mat))
count++;
if(count(i+1,j,mat))
count++;
if(count(i,j+1,mat))
count++;
}
}
}
return true;
}
Short explanation of what I am trying to do here: I am going about finding 1's on the board and when I find one I change it to a 0 and check its up,down,left,right for a 1. This goes on till I find no adjacent 1's. What is the thing I am missing here? I kind of have a feeling I am looping unnecessarily.

here's a solution without recursion
for(int i = 0; i < mat.length; i++) {
for(int j = 0; j < mat[i].length; j++) {
if(mat[i][j] == 1) {
if(i < mat.length - 1 && mat[i+1][j] == 1) {
count++;
}
if(j < mat[i].length - 1 && mat[i][j+1] == 1) {
count++;
}
}
}

I don't think recursion is the right answer as you should only being going one step deep (to find the adjacent value). Instead just loop through the elements looking to the right and down. Don't look up or left as twain mentioned so that you don't double count matches. Then is it simply:
for (i=0; i<max; i++)
for (j=0; j<max; j++)
if (array[i][j] == 1){
if (i<max-1 && array[i+1][j] == 1) count++;
if (j<max-1 && array[i][j+1] == 1) count++;
}

Related

3Sum on Leetcode

I'm working on the 3sum problem. I did it by sorting the array in the beginning and then using two pointer method to find all the unique triplets in the array which gives the sum of zero.
My question is that if I comment out the two while loops at the end, the runtime can be improved from 32ms to 26ms. I get a 6 ms speed boost. I think the time complexity is still O(n^2). Does anyone know why commenting out the while loops is faster?
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new LinkedList<List<Integer>>();
if(nums.length < 3){
return result;
}
int left = 0;
int right = nums.length - 1;
int threeSum = 0;
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2 && nums[i] <= 0; i ++) {
right = nums.length - 1;
if (i > 0) {
while (i < right && nums[i - 1] == nums[i])
i ++;
}
left = i + 1;
while (left < right) {
threeSum = nums[i] + nums[left] + nums[right];
if (threeSum == 0) {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
left ++;
right --;
while (left < right && nums[left - 1] == nums[left])
left ++;
while (left < right && nums[right + 1] == nums[right])
right --;
} else if (threeSum < 0) {
// move to the right
left ++;
// Skip duplicate numbers
// Comment this out get 6 ms speed increase
while (left < right && nums[left - 1] == nums[left])
left ++;
} else {
right --;
// Skip duplicate numbers
// Comment this out get 6 ms speed increase
while (left < right && nums[right + 1] == nums[right])
right --;
}
}
}
return result;
}

Codingbat how to count if there are three 3 in an array

Java newbie here, I'm doing some practice about array on Codingbat haveThree. This is the question :"Given an array of ints, return true if the value 3 appears in the array exactly 3 times, and no 3's are next to each other." My code works on most situation but not all.
My code:
public boolean haveThree(int[] nums){
int counter=0;
for(int i=0; i<nums.length-2;i++){
if(nums[i]==3){
counter++;
}
if(counter==3){
return true;
}
}
return false;
}
Can anyone help me and tell me where I was wrong? How can I fix it?
"Given an array of ints, return true if the value 3 appears in the
array exactly 3 times, and no 3's are next to each other."
you're almost there, however, there are a few mistakes and incomplete implementations:
you didn't check if the value 3 is next to another value 3 (in which case we return false)
you return as soon as count == 3 even though you didn't search the entire array to conclude that there is no more 3s.
as it stands your loop condition i < nums.length-2 doesn't include the last two elements of the array within the search.
solution:
public boolean haveThree(int[] nums){
int counter = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == 3){
counter++;
}
if(i + 1 < nums.length) {
if (nums[i] == 3 && nums[i + 1] == 3) return false;
}
}
if(counter == 3) return true;
return false;
}
Here is my solution for this, Have a look :)
public boolean haveThree(int[] nums) {
boolean check=true;
int count = 0;
for(int i=0;i<nums.length;i++){
if( nums[i]==3 && count++>0 && ( (i>0 && nums[i-1] == 3) || (i<nums.length-1 && nums[i+1] == 3) ) )
{//just checking if there are any consecutive 3's next to each other and counting them
check = false;
}
}
return (check && count==3);//count should be 3 and no 3's should be next to each other
}
Here is my solution, which passed all the tests on CodingBat:
public boolean haveThree(int[] nums) {
int counter3 = 0;
if (nums.length >= 5) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
counter3++;
}
}
}
if (counter3 == 3) {
for (int i = 0; i < nums.length - 4; i++) {
if ( (nums[i] == 3) &&
(nums[i+1] != 3) &&
(nums[i+2] == 3) &&
(nums[i+3] != 3) &&
(nums[i+4] == 3)
) { return true; }
}
}
return false;
}
Your loop does not lookup for each element you are missing the last 2 ones. Should be i < nums.length or use simply enhanced for so you don't have to save the current num on a value.
Check if no 3's are next to each other, because now you aren't checking that. I think the best salution to secure that no 3's are next to each other is to save the last number and compare it to the current one.
You can only be sure that the value 3 appears exactly 3 times in the array if you had seen the whole array so check that at the end and not in the loop.
public boolean haveThree(int[] nums) {
int lastNum = 0;
int counter = 0;
for (int currNum : nums) {
if (currNum == 3) {
counter++;
if (lastNum == currNum) {
return false;
}
}
lastNum = currNum;
}
return counter == 3;
}
A very Simple solution for this problem:
public boolean haveThree(int[] nums) {
int count = 0;
int preNum = 0;
for(int i =0; i<nums.length;i++){
if(nums[i]==3){
count++;
if(preNum ==3){
return false;
}
}
preNum = nums[i];
}
return count == 3;
}

Find the max sum path from bottom left side to top right cell

I have to find the maximum sum path in a 2d Array(n,m) given which has a value from 0 to 99999. 0 means wall. We have t start from the left bottom side of the array and must reach the right top cell(0,m-1). You can go up/down/right and can visit each cell once. Below is the code without any blocks .My problem is that i cant move from left bottom to right top cell . I also created left array(lest side of the main array) so that i can start from the best value possible .Sorry am not good programmer :).
Code
public static int maxvalue(int [][]field,int[] left)
{
for(int i=field.length-1;i>0 && left[i]!=-1;i--)
{
System.out.println( "Startpos "+i+" 0");
int distance =max(i,0,field,0,field.length-1);
if(distance>maxvalue)
maxvalue=distance;
}
return maxvalue;
}
public static int max(int r, int c,int [][]field ,int destR, int destC)
{
if(r>destR|| c>destC)
return 0;
if(r==0 && c==field[0].length)
return field[r][c];
int sum1=max(r-1,c,field,destR,destC); // up
System.out.println(sum1);
int sum2= max(r+1,c,field,destR,destC); //down
int sum3= max(r,c+1,field,destR,destC); //right
return field[r][c]+Math.max(sum1, Math.max(sum2, sum3));
}
Sample
Input
0 1 2 3
2 0 2 4
3 3 0 3
4 2 1 2
Output
25
How to do solve this question? if all the path is blocked then print No Solution.
Have you first tried to solve it by yourself?
It looks like a bit of work but it is not impossible.
What I would use is 3 int variables : xPosition, yPosition and Sum;
Go on and test the values of xPosition+1, yPosition-1 in priority and then the rest (because you want to reach xPosition == array.length - 1 && yPosition == 0.) and if you find a 0, test the other possibilities and exclude the ones you already passed by.
Each time you find a good path, add the value of the cell to your sum.
Reset it to 0 once you're blocked.
For every element in the array, you have to find the maximum of the adjacent elements and also check the boundary conditions. I hope this code will help you.
public class StackOverFlow {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
Integer [][] array = new Integer[n][m];
boolean [][] visited = new boolean[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
array[i][j] = in.nextInt();
}
}
int i = n-1, j =0;
visited[i][j] = true;
int sum = array[i][j];
while(true)
{
int max = -1;
int maxi = 0, maxj = 0;
if(i-1 >= 0 && i-1<= n-1 && j>=0 && j<= m-1 && array[i-1][j] != null && array[i-1][j]>max && !visited[i-1][j])
{
max = array[i-1][j];
maxi = i-1;
maxj=j;
}
if(i+1 >= 0 && i+1<= n-1 && j>=0 && j<= m-1 &&array[i+1][j] != null && array[i+1][j]>max && !visited[i+1][j])
{
max = array[i+1][j];
maxi = i+1;
maxj=j;
}
if(i >= 0 && i<= n-1 && j-1>=0 && j-1<= m-1 && array[i][j-1] != null && array[i][j-1]>max && !visited[i][j-1])
{
max = array[i][j-1];
maxi = i;
maxj=j-1;
}
if(i >= 0 && i<= n-1 && j+1>=0 && j+1<= m-1 && array[i][j+1] != null && array[i][j+1]>max && !visited[i][j+1])
{
max = array[i][j+1];
maxi = i;
maxj=j+1;
}
i = maxi;
j = maxj;
visited[i][j] = true;
sum += max;
if(i == 0 && j == m-1)
break;
}
System.out.println(sum);
}
}

Java 2D Array manipulation

I have to modify the below method:
private final static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
}
This method checks if it's a even number and if so it replaces its value with 0. Simple.
I now need to modify it so that it directs each cell to simultaneously replace its value with its number of diagonal neighbors that hold a value of 0.
I've thought about this for about an hour and tried many different solutions, most of which resulted in an out of bounds exception. I'm stumped and don't know how to accomplish this.
If the code is right, using the integers for the grid array below, it will reproduce the numbers shown in the bottom of the picture.
What is the problem, you just need to put if statements, like there can be maximum 4 possible neighbors so check that how many are equal to 0. But this is not enough you just need to add one more condition in each of the if statements. The condition would be that the neighbor you are trying to check is possible or not.
That is: Total 4 neighbors. If the coordinates of your main cell are x, y then:
1st Diagonal neighbor: x-1, y-1
2nd Diagonal neighbor: x-1, y+1
3rd Diagonal neighbor: x+1, y+1
4th Diagonal neighbor: x+1, y-1
These are all the 4 diagonal neighbors' coordinates but the last thing you need to check is whether they go out of bonds or not. For example for checking the 1st Diagonal neighbor I would do:
if((x-1)>0 && (y-1)>0){
//and then check here if that block is = `0`
}
and for other having say x+1 or y+1 you will need to check whether or not they are less than the NUM. Like if I want to check the 3rd Diagonal Neighbor:
if((x+1)<NUM && (y+1)<NUM){
//and then check here if that block is = `0`
}
Update: What do you mean by check here if that block is = 0?
If you want to check that is the diagonal neighboring blocks are equal to 0 or not then you will need to do it in a loop. Here is how:
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
for(row = 0; row< NUM; row++){
for(int col = 0; col < NUM; col++) {
int count = 0;
// To check for the 1st Diagonal Neighbor
if((row-1)>0 && (col-1)>0){
if(grid[row-1][col-1]==0){
count++;
}
}
//Similarly for 2nd, 3rd and 4th Diagonal Neighbors
//and then
grid[row][col]=count;
}
}
}
Update 2:
For say the 3rd diagonal neighbor the code block would be like this:
if((row+1)<NUM && (col+1)<NUM){
if(grid[row+1][col+1]==0){
count++;
}
}
Answer
final private static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
int counter = 0;
if((row - 1) > 0 && (col - 1) > 0) {
if(grid[row - 1][col - 1] == 0) {
counter++;
}
}
if((row - 1) > 0 && (col + 1) < NUM) {
if(grid[row - 1][col + 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col - 1) > 0) {
if(grid[row + 1][col - 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col + 1) < NUM) {
if(grid[row + 1][col + 1] == 0) {
counter++;
}
}
grid[row][col] = counter;
}
}
}

Search 2d Array

So im writing a java program which should find the shortest way from the entrance "2" to one of the numbers "3". It can only walk on " " positions. "1" is walls.
11111121
131 1
1 1 1111
1 1 13 1
1 1 11 1
1 1 1
1 1
11111111
My starting idea is to find the entrance in the 2d array. This could be done like this:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
I could also find the two "3" and save them in points. but im not sure how to return the rute to the closest "3". I was considering like a joystick, where I save the what direction you go, like (UP, DOWN, LEFT, RIGHT).
Then return the full list of moves from the entrance to the closests 3.
Got any suggestion or ideas how I could implement this ?
What you have here is simply a non-cannonical representation of a graph. You have each cell being a vertex in the graph and you have an edge between two neighboring cells if and only if both of them are free.
Now that you look at the problem in this way, find the entrance like you do and than do a breadth first search to find the exit.
I would try and create a graph with nodes and edges. Nodes are the junctions in the maze, and edges are the paths between junctions and entrance or exit objects. Each edge object has a 'weight'. Once you calculate the network from the double array, you can use some easy algorithm to work out the shortest route.
You need to make a counter that will increment every time the current position is " " (walk-able)
Notation " " = 0 in the matrix:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
Point firstexit = new Point(0,0);
int steps = 0;
int i = entrance.x;
int j = entrance.y;
int lasti = 0;
int lastj = 0;
while(true){
if(map[i][j] == 3){
firstexit.x =i;
firstexit.y =j;
break ;
}
if(map[i][j] == 0){
steps++;
}
// TO-DO : check if position exists
if(map[i][j+1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j++;
}else if(map[i][j-1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j--;
}else if(map[i+1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i++;
}else if(map[i-1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i--;
}
}

Categories