I am stuck on the following question:
Given a int two-dimensional matrix mat of size n2 where n = 2k, search for an integer k.
The matrix's rows and columns are sorted.
If we split the matrix in quarters, each quarter is also sorted. For example, given this matrix:
-4 -2 5 9
2 5 12 13
13 20 25 25
22 24 49 57
If we split it into quarters, we can see that all of the numbers in the first quarter are equal or less than numbers in the second quarter.
In order to obtain an efficient algorithm, I thought of making a recursive binary search in on the two dimensions but it fails to search for 2 on the previous matrix.
Here's the code:
public static boolean find(int[][] mat, int x){
return find2(mat, x, 0, mat.length-1,0, mat.length-1);
}
private static boolean find2(int[][] mat, int x, int lorow, int hirow,int locol,int hicol){
if(mat.length==0) return false;
if(lorow>hirow || locol>hicol) return false;
int midrow=(lorow+hirow)/2;
int midcol=(locol+hicol)/2;
if(mat[midrow][midcol] == x ) return true;
else if(mat[midrow][midcol] < x)
return find2(mat,x,lorow,midrow,midcol+1,hicol) || find2(mat,x,midrow+1,hirow,locol,midcol) || find2(mat,x,midrow+1,hirow,midcol+1,hicol);
else
return find2(mat,x,lorow,midrow,locol,midcol-1) || find2(mat,x,midrow,hirow,locol,midcol-1) || find2(mat,x,midrow+1,hirow,midcol+1,hicol);
}
Please advise.
Your mistake is at here in your code.
else
return find2(mat,x,lorow,midrow,locol,midcol-1) || find2(mat,x,midrow,hirow,locol,midcol-1) || find2(mat,x,midrow+1,hirow,midcol+1,hicol);
Here in first two functions, You are removing middle column from your search space. You need to include it as element can be present at the middle column. Another mistake is in the last call find2(mat,x,midrow+1,hirow,midcol+1,hicol).
If your search element is smaller than the middle element, You should choose top-left quadrant of the middle element and ignore the bottom-right quadrant. You have mistakenly considered here bottom-right quadrant over top-left quadrant.
After making changes accordingly the return function in else looks like:
return find2(mat,x,lorow,midrow,locol,midcol) || find2(mat,x,lorow,midrow,midcol+1,hicol) ||find2(mat,x,midrow+1,hirow,locol,midcol);
This solved the problem and it returns true for -2.
Updated Code:
private static boolean find2(int[][] mat, int x, int lorow, int hirow,int locol,int hicol){
if(mat.length==0) return false;
if(lorow>hirow || locol>hicol) return false;
if(lorow==hirow && locol==hicol && mat[lorow][locol]!=x)
return false;
int midrow=(lorow+hirow)/2;
int midcol=(locol+hicol)/2;
if(mat[midrow][midcol] == x ) return true;
else if(mat[midrow][midcol] < x)
return find2(mat,x,lorow,midrow,midcol+1,hicol) || find2(mat,x,midrow+1,hirow,locol,midcol) || find2(mat,x,midrow+1,hirow,midcol+1,hicol);
else
return find2(mat,x,lorow,midrow,locol,midcol) || find2(mat,x,lorow,midrow,midcol+1,hicol) ||find2(mat,x,midrow+1,hirow,locol,midcol);
}
If your matrix row and column are sorted you can use below code.
public int search(int mat[][], int n, int x) {
int i = 0, j = n - 1;
while (i < n && j >= 0) {
if (mat[i][j] == x) {
System.out.println("Found at" + i + j);
return 1;
}
if (mat[i][j] > x)
j--;
else // if mat[i][j] < x
i++;
}
System.out.println("not Found at");
return 0;
}
Related
I need to write a recursive, boolean method which receives a 1d array and a number num.
The method checks if a subarray whose length is equal to or less than 3 and it's elements can be summed to num, in a few conditions:
the numbers are non consecutive.
2.cannot use the same number twice.
Examples:
array: {5,4,2,1,3}, number = 9 - returns true because 4+5 = 9.
This one is valid as 4,5 are consecutive but it's not a triplet of numbers.
number = 8 - returns true because 5+3 = 8, 4 + 3 + 1 = 8.
number = 11 - returns false because 5+4+2 = 11 but elements are consecutive.
Below is what I've written so far:
public static boolean isSum(int[]a,int num){
return isSum(a,0,0,0,num);
}
private static boolean isSum(int[]a, int i, int sum,int counter,int num){
if(i > a.length - 1 || a[i] == -1||counter > 3){
return false;
}
if(sum == num&& !(sum == a[i] + a[i+1] + a[i+2] || sum == a[i-1] + a[i] + a[i+1] || sum ==
a[i-2] + a[i-1] +a[i])){
return true;
}
int k = a[i];
a[i] = -1;
boolean notused = isSum(a, i+1, sum, counter, num);
boolean used = isSum(a,i+1,sum+a[i],counter +1, num);
a[i] = k;
return used||notused;
}
The logic is as following: the method either takes the current element and adds it to sum, or it skips is. every time we take an element we add 1 to counter, and then we turn the element we've used to -1 in order to not use it again.
the method will return true only if sum == num and sum != 3 consecutive order numbers.
This method returns only false. any idea why?
Basically, I am trying to write a method where a number is inputted and if there are more odd digits than even digits in the number, it returns "true", and else, false. I think I need to use tail recursion but I cannot figure it out.
public static boolean moreOddThanEven(int x) {
if (x == 0) {
return false;
}
if (x % 2 == 0) {
return moreOddThanEven(x / 10);
} else {
return moreOddThanEven(x / 10);
}
}
public static boolean moreOddThanEven2(int x) {
return moreOddThanEvenTR(x, 0, 0);
}
public static boolean moreOddThanEvenTR(int x, int odd, int even) {
if (x == 0) {
return false;
}
if (x%2==0) {
return moreOddThanEvenTR(x / 10, odd, even+1);
}
if (x%2!=0) {
return moreOddThanEvenTR(x / 10, odd+1, even);
}
if (odd <= even) {
return false;
} else {
return true;
}
}
I think using tail recursion is the right idea. Here is my attempt, assuming we can use more than one parameter in the recursive function:
public static boolean compareOddEven(int x, int count) {
//This is when we reach the end of the recursion (ones place).
if(x<10) {
//if odd, add 1, if even subtract 1
count += (x%2==1) ? 1 : -1;
return count>0;
}
else{
int digit = x;
//We use this loop in order to get the leftmost digit and read whether it is odd or even.
//Subsequently, we add or subtract 1 to the count based on the digit's parity and we pass this count into the next recursion in order to keep track.
while (digit > 9) {
digit /= 10;
}
count += (digit%2==1) ? 1 : -1;
//Get rid of the first digit to get next number to use in recursive call.
int removedFirstDigit = x % (int) Math.pow(10, (int) Math.log10(x));
//tail recursion
return compareOddEven(removedFirstDigit, count);
}
}
Explanation. We can accomplish this with just one method if we keep track of the count of odd and even digits the second parameter of the method. It will be less cumbersome to keep track of the count rather than keeping track of both counts of the odd and even numbers (and avoids the comparisons at the end which would not make it a tail recursion).
With this in mind, our approach is to start at the leftmost digit of the number we input and move to the right with each new recursive call. It is possible to start from right and go left in counting the parity of the digits as well.
So with every new recursive call, we pass in the count to the function as an argument. When we finally reach the ones digit, the nonnegativity of the count tells us whether there are more odd or even digits. To see this more clearly, I recommend printing out some of the arguments right before the recursive call is made.
Further note that when we reach the ones place, the truth value of count>0 will be propagated up the chain of recursive calls to give the final result that we desire.
Example call:
System.out.println(compareOddEven(21468233, 0));
Output:
false
There is a simple reason why you are stuck: you have to count the evens/odds like in 77778888888999. In fact you need to count the sum of (odds - evens), the oddity.
public static boolean moreOddThanEven(int x) {
assert x >= 0;
return x != 0 && oddity(x) > 0;
}
private static int oddity(int x) {
if (x == 0) {
return 0;
}
if (x % 2 == 0) {
return oddity(x / 10) - 1;
} else {
return oddity(x / 10) + 1;
}
}
Recursion is not needed (nor is more than one line):
public static boolean moreOddThanEven(int x) {
return (""+x).replaceAll("[02468]", "").length() > ((int) Math.log10(x)+1) / 2;
}
or the longer, but non-mathy version:
public static boolean moreOddThanEven(int x) {
return (""+x).replaceAll("[02468]", "").length() > ((int) (""+x).replaceAll("[13579]", "").length();
}
If you have an easier time thinking about loops than tail recursion, it's worth knowing that you can translate any loop into tail recursion (and vice versa, but that's different topic). First, we need to get the loop into this shape:
initialize a, b, ...
while (<some condition on a, b, ...>) {
Update a, b, ... using old values of a, b, ...
}
return <any function of a, b ...>
it translates to:
TypeOfReturn while_loop(TypeOfA a, TypeOfB b, ...) {
if (!(<some condition on a, b, ...>)) {
return <any function of a, b, c ...>;
}
Update a, b, ... using old values of a, b, ...
return while_loop(a, b, ...);
}
Let's apply this to your problem. As a loop:
// x is the input
int oddMinusEven = 0;
while (x) {
oddMinusEven += 2 * (x % 2) - 1;
x /= 10;
}
return oddMinusEven > 0;
We get:
bool hasMoreOddThanEvenDigits(int x, int oddMinusEven) {
if (!x) return oddMinusEven > 0;
oddMinusEven += 2 * (x % 2) - 1;
x /= 10;
return hasMoreOddThanEvenDigits(x, oddMinusEven);
}
We can clean this up a bit to make it less verbose:
int hasMoreOddThanEvenDigits(int x, int oddMinusEven) {
return x ? hasMoreOddThanEvenDigits(x / 10, oddMinusEven + 2 * (x % 2) - 1) : oddMinusEven > 0;
}
We run the loop with a "top level" function call that initializes variables:
return getMoreOddThanEvenDigits(x, 0) > 0;
It's fun to see what a good compiler does with the two codes. As you'd expect, they lead to nearly identical machine code. If we can do a rule-based transformation, so can the compiler.
I have the following two solutions for the following algo problem:
Suppose you have N integers from 1 to N. We define a beautiful
arrangement as an array that is constructed by these N numbers
successfully if one of the following is true for the ith position (1 <=
i <= N) in this array:
The number at the ith position is divisible by i.
i is divisible by the number at the ith position. Now given N, how many beautiful
arrangements can you construct? (N will be <= 15)
Here's the provided solution in Java:
public class Solution {
int count = 0;
public int countArrangement(int N) {
boolean[] visited = new boolean[N + 1];
calculate(N, 1, visited);
return count;
}
public void calculate(int N, int pos, boolean[] visited) {
if (pos > N)
count++;
for (int i = 1; i <= N; i++) {
if (!visited[i] && (pos % i == 0 || i % pos == 0)) {
visited[i] = true;
calculate(N, pos + 1, visited);
visited[i] = false;
}
}
}
}
And here's my Ruby solution:
def count_arrangement(n)
visited = Array.new(n + 1) # zero index left blank
count_arrangements(n, visited, 1)[:arrangements]
end
def count_arrangements(n, visited, i)
return { arrangements: 1, recursed: true } if i == n + 1 # this is end of one arrangement
max_arrangements = 0
recursed = false
1.upto(n) do |num|
next if visited[num]
if num % i == 0 || i % num == 0
recursed = true
this_visited = visited.dup
this_visited[num] = true
arrangements_obj = count_arrangements(n, this_visited, i + 1) # recursive depth only goes up to O(N)
if arrangements_obj[:recursed]
max_arrangements += arrangements_obj[:arrangements]
end
end
end
recursed ? { arrangements: max_arrangements, recursed: true } : { arrangements: -1, recursed: false }
end
Seems like the algorithmic complexity is the same (AFAIK), and yet my Ruby solution times out where the Java one doesn't. Does anyone know why this is?
Can anyone please help me understand this code?
This code is used to solve this problem.
You are playing a game on your cellphone. You are given an array of length n, indexed from 0 to n−1. Each element of the array is either 0 or 1. You can only move to an index which contains 0. At first you are at the 0th position. In each move you can do one of the following things:
Walk one step forward or backward.
Make a jump of exactly length m forward.
That means you can move from position x to x+1, x−1 or x+m in one move. The new position must contain 0. Also you can move to any position greater than n-1.
You can't move backward from position 0. If you move to any position greater than n−1, you win the game.
Given the array and the length of the jump, you need to determine if it's possible to win the game or not.
n = sc.nextInt();
m = sc.nextInt();
field = new int[n];
for (int i = 0; i < n; i++) {
field[i] = sc.nextInt();
}
if (makeMove(0, new LinkedList<Integer>()))
System.out.println("YES");
else
System.out.println("NO");
.
.
.
private boolean makeMove(int position, List<Integer> prevPositions)
{
if (prevPositions.contains(position))
return false;
prevPositions.add(position);
if (position < 0) return false;
else if (position >= n) return true;
else if (field[position] == 1) return false;
else {
return makeMove(position + m, prevPositions) ||
makeMove(position + 1, prevPositions) ||
makeMove(position - 1, prevPositions);
}
}
input: 6 2
0 0 0 1 0 0
Output: Yes
input: 6 2
0 0 1 1 0 0
Output: No
So, I am assuming that you understand the concept of recursion, which is calling a method within itself, if not you may want to look it up.
The first section of code is very simple. It initializes the move length m and the array of length n and populates it with random binary digits.
The makeMove method goes through a few base cases to see if a branch of recursion has failed or succeeded.
1.) if (prevPositions.contains(position))
return false;
prevPositions.add(position);
After making a move, this code checks whether you have already gotten to this position. If you have, it returns false because this case has already been known to be false, otherwise the method would have already returned true.
2.) if (position < 0) return false;
else if (position >= n) return true;
else if (field[position] == 1) return false;
-You can't have a negative position, so that returns false.
-If your position is greater than n then you win, so return true
-You can't move to a position that contains a non-zero digit, so return false
3.) return makeMove(position + m, prevPositions) ||
makeMove(position + 1, prevPositions) ||
makeMove(position - 1, prevPositions);
This code makes recursive calls to other moves from possible positions and returns true if any of these calls are true. Since you can leap to position+m, then it makes sense that if makeMove(position+m, prevPositions) is true, then makeMove(position, prevPositions) is also true. Similarly you can move to position+1 and position-1 so calls to makeMove of these positions should return the same value as makeMove of your original position. Hope this made sense!
This solution works fine. Please try this. you need to pass, the element array length and the jump values.
public static boolean decideMove(int[] elements, int length, int jump){
boolean result = false;
boolean makeMove = true;
int currentPosition = 0;
while(makeMove){
if (currentPosition + jump > length-1){
return true;
}
if(elements [currentPosition + jump] == 0){
currentPosition = currentPosition + jump;
if (currentPosition + jump > length-1){
return true;
}
}
if (elements[currentPosition + 1] == 0){
currentPosition = currentPosition + 1;
if (currentPosition + jump > length-1){
return true;
}
}
if(elements[currentPosition +1] ==1 && elements[currentPosition + jump]==1){
if(elements[currentPosition - 1]==0){
currentPosition = currentPosition - 1;
} else{
return false;
}
}
}
return result;
}
The problem is the following:
Given a matrix of characters. In the very beginning of the game I am at position (0, 0) in the matrix. Depending on the character in the current position (i, j) I can move Up (if the current character is 'U'), Down if the current character is 'D', Right if the current character is 'R' and Left if the current character is 'L'. Once I reach position with character '*' I cannot move any more (there is exactly one such position). I have some time K in which I have to reach the character. I also have right to change characters, s.t. I can reach character ' * ' faster, but for each changing I pay cost of 1. In the end I have to return the min number of changes I have performed s.t. I have to reach character ' * ' in time k. If it is not possible I have to return -1.
My idea is as follows:
traverse the whole matrix, to find the position of character ' * '.
create boolean method isReachable(x, y, k), which tells me if character at position (x, y) is reachable from position (0, 0) for time k. Here is the method:
public static boolean isReachable(int x, int y, int time){
if(time < 0){
return false;
}
if(x == 0 && y == 0){
return true;
}
if(isInBounds(x-1, y)){
if(maze[x-1][y] == 'D'){
return isReachable(x-1, y, time-1);
}
}
if(isInBounds(x, y-1)){
if(maze[x][y-1] == 'R'){
return isReachable(x, y-1, time-1);
}
}
if(isInBounds(x+1, y)){
if(maze[x+1][y] == 'U'){
return isReachable(x+1, y, time-1);
}
}
if(isInBounds(x, y+1)){
if(maze[x][y+1] == 'L'){
return isReachable(x, y+1, time-1);
}
}
return false;
}
private static boolean isInBounds(int x, int y) {
if(x >= 0 && x <= N-1 && y >= 0 && y <= M-1){
return true;
}
return false;
}
If the method return true - I output 0 (i.e. there is no need to change any square in the matrix).
If the method return false - I want to perform another method which will tell me the min number of changes. However I dont know how to write it. This is my draft that obiously doesnt work:
private static int find(int x, int y, int k) {
int res = 0;
if(k < 0){ //my idea is that if the time become < 0 it means that the point is unreachable, i.e. I have to output 0; Howevr this doesnt output 0, just gives 0 to the upper levels of a recursion tree;
return -1;
}
if(x == 0 && y == 0){
res = 0;
}
else{
int down;
if(isInBounds(x-1, y) ){
if(maze[x-1][y] == 'D'){
down = find(x-1, y, k-1);
}
else{
down = 1 + find(x-1, y, k-1);
}
}
else{
down = Integer.MAX_VALUE;
}
int left;
if(isInBounds(x, y+1) ){
if(maze[x][y+1] == 'L'){
left = find(x, y+1, k-1);
}
else{
left = 1 + find(x, y+1, k-1);
}
}
else{
left = Integer.MAX_VALUE;
}
int right;
if(isInBounds(x, y-1) ){
if(maze[x][y-1] == 'R'){
right = find(x, y-1, k-1);
}
else{
right = 1 + find(x, y-1, k-1);
}
}
else{
right = Integer.MAX_VALUE;
}
int up;
if(isInBounds(x+1, y) ){
if(maze[x+1][y] == 'U'){
up = find(x+1, y, k-1);
}
else{
up = 1 + find(x+1, y, k-1);
}
}
else{
up = Integer.MAX_VALUE;
}
res = min(left, right, up, down);
}
return res;
}
As I wrote in the comments I have two very basic cases which I dont know how to perform:
when the time < 0 -> it means that the point is unreachable, i.e. I have to output -1 (but I dont know how to do it)
if I am at point (0, 0) I dont have to do any changes - return 0
else I check the neighbouring squares for their letters and return what I have from them.
Can someone help me with general idea, because I think mine is wrong. I the problem description it was said that we have to use dynamic programming and recursion
I haven't solve the problem, but I think my solution is right.
create dp[i][j][dir][step], means the cost in pos(i,j), the direction is dir and need 'step' steps to the position '*'.
assume '*' in I,J, so we need to calculate dp[I][J][0|1|2|3][0].
tot time is states*move, which is (50*50*4*1000)*(4*4). It is enough to solve the problem.