Incorrect result from dynamic programming algorithm - java

I am trying to solve the Dynamic Problem question to find unique paths between origin and the last cell of a board. The problem is present on leetcode here https://leetcode.com/problems/unique-paths/.
The problem statement is -
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
I am stuck on a test case with m = 23 and n = 12. Can you please explain the inconsistency in my code?
public int uniquePaths(int m, int n) {
return getPath(m,n,1,1);
}
HashMap<String,Integer> map = new HashMap<>();
private int getPath(int m, int n, int x, int y){
if(x == n && y == m) return 1;
else if(x > n || y > m) return 0;
String s = ""+x+y;
if(map.get(s) != null) return map.get(s);
int max =0;
if(x < n)
max = max + getPath(m,n,x+1,y);
if(y < m)
max = max + getPath(m,n,x,y+1);
map.put(s,max);
return max;
}
}
On m = 23 and n = 12, I am getting 192184665 as output whereas 193536720 is the expected result.

Look into my comment. You can solve this in Sigma (m * n) with bottom-up dp.
Create an int matrix of size [m * n].
int[] a = new int[n][m];
for (int i = 0; i < n-1; ++i) {
a[i][m-1] = 1;
}
for (int j = 0; i < m-1; ++j) {
a[n-1][j] = 1;
}
for (int i = n-2; i >= 0; --i) {
for (int j = m-2; j >= 0; --j) {
a[i][j] = a[i+1][j] + a[i][j+1];
}
}
System.out.print(a[0][0]);

Related

Improve Efficiency of Alog (Rotate Array to Left by n iterations)

I am solving a challenge to rotate array to left by n number of iterations.
Code is pretty much working but lags on very very huge input.
How to more improve efficiency
// Complete the rotLeft function below.
static int[] rotLeft(int[] a, int iterations) {
for(int i=0;i<iterations;i++)
{
int[] temp=Arrays.copyOfRange(a, 1, a.length);
temp=Arrays.copyOf(temp,a.length);
temp[a.length-1]=a[0];
a=temp;
}
return a;
}
Suggestions are welcome.
Thanks
Instead on shifting iterations you can calculate the final position directly.
finalIndex=(index-iterations+a.length) % a.length
+a.length is added to ensure that the finalIndex is always a not negattive value.
If you apply this to your algorithm, you get rid of the loop and do the whole thing in one step.
This reduced time complexity of the algorithm from O(a.length*iterations) to O(a.length).
There are few flaws in the code.
First, you do redundant work - if iterations > a.length - then after a.length iterations the array just returns back to itself.
Second, each iteration creates a whole new copy of the array!
Third, the new location of each element in the array can be predetermined by looking only on the array length, the number of iterations required, and the index of this element, no need to repeatidly go over iterations.
When taking these into considerations, this can boil down to something in the form of:
static int[] rotLeftEfficient(int[] a, int iterations) {
iterations = iterations % a.length;
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
int newIndex = (i - iterations + a.length) % a.length;
b[newIndex] = a[i];
}
return b;
}
This boils down to O(n) solution - where n is the number of elements in the array, with decent constants as well.
Here is a rotate in place (doesn't use a second array), with O(a.length) time complexity. On my system (Intel 3770K 3.5ghz), it can rotate a 2^28 = 268,435,456 element array in .17 (rotate 76) to .85 seconds (rotate 1). The swaps are done in sequential access sequences, which is cache friendly.
// rotate in place
public static void rolip(int[] a, int r){
r = r % a.length;
if(r == 0)
return;
int t;
int n = a.length - r;
int i = 0;
int j;
while(true){
if(r <= n){ // shift left r places
for(j = i+r; i < j; i++){
t = a[i]; // swap(a[i], a[i+r])
a[i] = a[i+r];
a[i+r] = t;
}
n -= r;
if(n == 0)
break;
} else { // shift right n places
i += r;
for(j = i+n; i < j; i++){
t = a[i]; // swap(a[i], a[i-n])
a[i] = a[i-n];
a[i-n] = t;
}
i -= n+r;
r -= n;
if(r == 0)
break;
}
}
}
Simple rotate using a second array. On my system (Intel 3770K 3.5ghz), it can rotate a 2^28 = 268,435,456 element array in .11 to .50 seconds.
public static void rol(int[] a, int r){
r = r % a.length;
if(r == 0)
return;
int n = a.length - r;
int i;
int j;
if(r <= n){ // if left rotate
int[] b = new int[r]; // save elements
for(j = 0; j < r; j++)
b[j] = a[j];
for(i = 0; i < n; i++) // shift elements
a[i] = a[j++];
for(j = 0; j < r; j++) // copy saved elements
a[i++] = b[j];
} else { // else right rotate
int[] b = new int[n]; // save elements
i = 0;
for(j = r; j < a.length; j++)
b[i++] = a[j];
i = j-1; // shift elements
for(j = i-n; j >= 0; j--)
a[i--] = a[j];
for(j = 0; j < n; j++) // copy saved elements
a[j] = b[j];
}
}
You don't need to do it for every iteration. Instead you can create a formula to figure out where every element would go.
For example, let's say that the size of your array is n.
Then, if you need to move your array to the left by 1 iteration, then an element at position p would be at (p + 1) % n position.
For i iterations, every element would be at (p + i) % n location. So, a loop for every iteration is not needed.
static int[] rotLeft(int[] a, int iterations) {
int[] answer = new int[a.length];
for(int i=0;i<a.length;i++)
{
answer[i] = a[(i - iterations + a.length) % (a.length)];
}
return answer;
}
What about this:
static int leftRotate(int arr[], int iterations,
int k)
{
/* To get the starting point of
rotated array */
int mod = k % iterations;
// Prints the rotated array from
// start position
for(int i = 0; i < iterations; ++i)
System.out.print(arr[(i + mod) % iterations]
+ " ");
System.out.println();
}
leftRotate(arr, iterations, arr.length);
Ref: https://www.geeksforgeeks.org/print-left-rotation-array/

My recursive function for finding the number of paths in a grid runs infinitely

I'm working on a couple of Project Euler problems and want to test my solution. My recursive function never ends even with reachable base cases.
in a 20x20 grid I am using x and y coordinates to navigate up and left to find the number of paths from (19,19) to (0,0). My base case is to return 1 when we reach (0,0). Otherwise I add the current count to the recursive call.
Function:
private static int numPaths(int x, int y, int pathsFound)
{
if(x == 0 && y == 0)
return 1;
else
{
if(x > 0)
{
pathsFound += numPaths(x - 1, y, pathsFound);
}
if(y > 0)
{
pathsFound += numPaths(x, y - 1, pathsFound);
}
}
return pathsFound;
}
Main:
int x = 19;
int y = 19;
System.out.println("Answer: " + numPaths(x, y, 0));
Is there a flaw in my recursive logic, or is just taking a very long time to compute? If you know the solution to this Euler problem, please do not post it.
https://projecteuler.net/problem=15
So if anyone is interested, I looked into memoization and came up with an elegant solution without recursion.
Function:
private static BigInteger numberPaths(ArrayList<ArrayList<BigInteger>> grid)
{
for(int i = 0; i <= 20; ++i)
{
for(int j = 0; j <= 20; ++j)
{
int x = j;
int y = i;
if(x - 1 < 0 || y - 1 < 0)
{
grid.get(x).set(y, BigInteger.ONE);
}
else
{
BigInteger topVal = grid.get(x - 1).get(y);
BigInteger leftVal = grid.get(x).get(y - 1);
grid.get(x).set(y, topVal.add(leftVal));
}
}
}
return grid.get(20).get(20); //the solution
}
Main:
ArrayList<ArrayList<BigInteger>> grid = new ArrayList<>();
for(int i = 0; i <= 20; ++i)
{
ArrayList<BigInteger> column = new ArrayList<>();
for(int j = 0; j <= 20; ++j)
{
column.add(BigInteger.valueOf(0));
}
grid.add(column);
}
System.out.println("Answer: " + numberPaths(grid));

Rotate matrix confusion in Java

public int[][] Solution(int[][] matrix, int flag) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return matrix;
//int m = matrix.length, n = matrix[0].length;
int[][] rvalue;
rvalue = transpose(matrix);
flip(rvalue, flag);
return rvalue;
}
// transporse the matrix
private int[][] transpose(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] rvalue = new int[n][m];
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
rvalue[i][j] = matrix[j][i];
return rvalue;
}
// clockwise rotate the matrix
private void flip(int[][] matrix, int flag) {
int m = matrix.length, n = matrix[0].length;
if (flag == 1) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n / 2; j++) {
matrix[i][j] ^= matrix[i][n-j-1]; // line 1
matrix[i][n-j-1] ^= matrix[i][j]; // line 2
matrix[i][j] ^= matrix[i][n-j-1]; // line 3
}
}
}
Above is the code for rotating the matrix (first transporse, then rotate). But I cannot understand the code for line 1,2 and 3, I replaced these three lines with my own following code and it works well.
int temp=matrix[i][j];
matrix[i][j]=matrix[i][matrix[0].length-j-1];
matrix[i][matrix[0].length-j-1]=temp;
Can someone explain what the original three lines doing?
The 3 lines are using the xor operator to exchange values.
I would never use it unless you really are hard pressed for memory because, as you obviously noticed, it's very hard to understand.
Here's a link to some info on the algorithm it's using to exchange the values

What is the Complexity of my function?

I want to find the Complexity of my function and i am not sure if it's O(n) or maybe something else
public static boolean find(int [][] mat, int x)
{
int i = 1;
int j = 0;
int k = 0;
int row = 0;
int col = 0;
int n = mat.length;
while(i < n)//(see method discription)stage 1. loops over maxuim of n/2 times = O(n)
{
i = i * 2;
if(x == mat[i-1][i-1])
return true;
else if (x < mat[i-1][i-1])
{
k = i / 2;
row = col = i-1;
break; //bigger value then x found, x is within the max and min values of the matrix. moving on to find a match.
}
}
if (i > n)//x is bigger then max value of mat
return false;
for (j = k; j > 1; j = j / 2)//stage 2. locking on the right 2x2 matrix. runs k times. k<n O(n)
{
if(x == mat[row-j][col] || x == mat[row][col-j])
return true;
else if(x < mat[row-j][col])
row = row - j;
else if (x < mat[row][col-j])
col = col - j;
}
//checking if x is within this 2x2 matrix
if(x == mat[row][col-1])
return true;
else if(x == mat[row-1][col])
return true;
else if(x == mat[row-1][col-1])
return true;
else
return false;
}
I would say O(log2(n)):
first loop does log2(n) max iterations
second loop depends on k < log2(n) and does max log2(k) operations

Searching a word in a given string array

You are given a 2D array as a string and a word via keyboard. The word
can be in any way (all 8 neighbors to be considered) but you can’t use
same character twice while matching. Return word's first and last
character's index as (x,y). If match is not found return -1.
That's the question. I'm having trouble with searching. I tried that:
int x=0,y=0;
for(int f=0; f<WordinArray.length; f++){
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(matrix[i][j].equals(WordinArray[f])){
x=i; y=j;
System.out.print("("+x+","+y+")");
}
}
}
}
But, That code is not working as it is supposed to. How else I can write this searching code?
Referring to Sixie's code
Assuming this is a valid input/output to your program?
Size:
4x4
Matrix:
a b c d
e f g h
i j k l
m n o p
Word: afkp
(0,0)(3,3)
I edited your code, so that it should work for input on this form (it is case sensitive at the moment, but can easily be changed by setting .toLowerCase()
Scanner k = new Scanner(System.in);
System.out.println("Size: ");
String s = k.nextLine();
s.toUpperCase();
int Xindex = s.indexOf('x');
int x = Integer.parseInt(s.substring(0, Xindex));
int y = Integer.parseInt(s.substring(Xindex + 1));
System.out.println("Matrix:");
char[][] matrix = new char[x][y];
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
matrix[i][p] = k.next().charAt(0);
}
}
System.out.print("Word: ");
String word = k.next();
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
// looping through the matrix
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
// when a match is found at the first character of the word
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
// calculating all the 8 normals in the x and y direction
// (the 8 different directions from each cell)
for (int normalX = -1; normalX <= 1; normalX++) {
for (int normalY = -1; normalY <= 1; normalY++) {
// go in the given direction for the whole length of
// the word
for (int wordPosition = 0; wordPosition < word
.length(); wordPosition++) {
// calculate the new (x,y)-position in the
// matrix
int xPosition = i + normalX * wordPosition;
int yPosition = j + normalY * wordPosition;
// if the (x,y)-pos is inside the matrix and the
// (x,y)-vector normal is not (0,0) since we
// dont want to check the same cell over again
if (xPosition >= 0 && xPosition < x
&& yPosition >= 0 && yPosition < y
&& (normalX != 0 || normalY != 0)) {
// if the character in the word is not equal
// to the (x,y)-cell break out of the loop
if (matrix[xPosition][yPosition] != word
.charAt(wordPosition))
break;
// if the last character in the word is
// equivalent to the (x,y)-cell we have
// found a full word-match.
else if (matrix[xPosition][yPosition] == word
.charAt(wordPosition)
&& wordPosition == word.length() - 1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xPosition;
yEnd = yPosition;
}
} else
break;
}
}
}
}
}
}
System.out.println("(" + xStart + "," + yStart + ")(" + xEnd + ","
+ yEnd + ")");
k.close();
I think you need to plan your algorithm a bit more carefully before you start writing code. If I were doing it, my algorithm might look something like this.
(1) Iterate through the array, looking for the first character of the word.
(2) Each time I find the first character, check out all 8 neighbours, to see if any is the second character.
(3) Each time I find the second character as a neighbour of the first, iterate along the characters in the array, moving in the correct direction, and checking each character against the word.
(4) If I have matched the entire word, then print out the place where I found the match and stop.
(5) If I have reached the edge of the grid, or found a character that doesn't match, then continue with the next iteration of loop (2).
Once you have your algorithm nailed down, think about how to convert each step to code.
If I understood your question right. This is a quick answer I made now.
int H = matrix.length;
int W = matrix[0].length;
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
String word = "WordLookingFor".toLowerCase();
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int k = 0; k < word.length(); k++) {
int xx = i+x*k;
int yy = j+y*k;
if(xx >= 0 && xx < H && yy >= 0 && yy < W && (x != 0 || y != 0)) {
if(matrix[xx][yy] != word.charAt(k))
break;
else if (matrix[xx][yy] == word.charAt(k) && k == word.length()-1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xx;
yEnd = yy;
}
} else
break;
}
}
}
}
}
}
A little trick I used for checking all the 8 neighbors is to use two for-loops to create all the directions to go in:
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if(x !=0 || y != 0)
System.out.println(x + ", " + y);
}
}
This creates
-1, -1
-1, 0
-1, 1
0, -1
0, 1
1, -1
1, 0
1, 1
Notice: All but 0,0 (you don't want to revisit the same cell).
The rest of the code is simply traversing though the matrix of characters, and though the whole length of the word you are looking for until you find (or maybe you don't find) a full match.
This time the problem is that how could I print word's first and last
letter's indexes. I tried various ways like printing after each word
was searched. But, all of them didn't work. I am about to blow up.
int[] values = new int[2];
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(Character.toString(word.charAt(0)).equals(matrix[i][j]) == true || Character.toString(ReversedWord.charAt(0)).equals(matrix[i][j]) == true ){
System.out.print("("+ i + "," +j+")");
//First letter is found.Continue.
for(int p=1; p<word.length(); p++){
try{
for (int S = -1; S <= 1; S++) {
for (int SS = -1; SS <= 1; SS++) {
if(S !=0 || SS != 0)
if(matrix[i+S][j+SS].equals(Character.toString(word.charAt(p))) && blocksAvailable[i+S][j+SS] == true ||
matrix[i+S][j+SS].equals(Character.toString(ReversedWord.charAt(p))) && blocksAvailable[i+S][j+SS] == true) {
values[0] = i+S;
values[1] = j+SS;
blocksAvailable[i+S][j+SS] = false;
}
}
}
}catch (ArrayIndexOutOfBoundsException e) {}

Categories

Resources