Apologies for the ambiguous title, I could not think of something more specific.
In order to get better at solving problems recursively, I have been tackling the questions posted on CodingBat. My question is related to a variation of the following problem.
The original problem is:
Given an array of ints, compute recursively if the array contains
somewhere a value followed in the array by that value times 10. We'll
use the convention of considering only the part of the array that
begins at the given index. In this way, a recursive call can pass
index+1 to move down the array. The initial call will pass in index as
0.
array220({1, 2, 20}, 0) → true
array220({3, 30}, 0) → true
array220({3}, 0) → false
My solution to this problem is:
public boolean array220(int[] nums, int index) {
if (index >= nums.length-1) return false;
if (nums[index+1] == nums[index] * 10) return true;
return array220(nums, ++index);
}
However, in order to challenge myself, I was wondering how I would go about solving the following variation of this problem that I conceived:
Given an array of ints, compute recursively if the array contains
somewhere a value that is 10 times larger than any other value. We'll use
the convention of considering only the part of the array that begins
at the given index. In this way, a recursive call can pass index+1 to
move down the array. The initial call will pass in index as 0.
For example:
array220({1, 2, 10}, 0) → true
array220({3, 2, 9, 38, 20}, 0) → true
array220({3}, 0) → false
So basically, the difference with the original problem is that the values may not necessarily be adjacent to one another (see examples above).
How would I go about doing this recursively? I would appreciate some pointers.
I do not want to change the method signature or use global variables.
This can be the answer, just making use of a HashSet, and passing it along when you make recursive call:
public boolean array220(int[] nums,HashSet<Integer> set, int index) {
if (index >= nums.length-1) return false;
if (set.contains(nums[index]*10))
return true;
set.add(nums[index]);
return array220(nums,set, ++index);
}
If you don't want to use additional data structures, sorting array and making use of binary search can bring you an O(nlogn) solution, with two recursive methods.
Arrays.sort(nums);
public boolean array220(int[] nums, int index) {
if (index >= nums.length-1) return false;
if (binarySearch(index + 1, nums.length - 1,nums[index]*10,nums))
return true;
return array220(nums, ++index);
}
public boolean binarySearch(int start, int end,int value, int[] nums){
if(start > end)
return false;
int mid = (start + end)/2;
if(nums[mid] == value){
return true;
}else if(nums[mid] > value){
return binarySearch(start, mid - 1, value, nums);
}else{
return binarySearch(mid + 1, end, value, nums);
}
}
If you don't want to sort the array, using a linear recursive search will give a O(n^2) solution.
public boolean array220(int[] nums, int index) {
if (index >= nums.length-1) return false;
if (linearSearch(0,nums[index]*10,nums))
return true;
return array220(nums, ++index);
}
public boolean linearSearch(int start, int value, int[] nums){
if(start >= nums.length)
return false;
if(nums[start] == value){
return true;
}else {
return linearSearch(start + 1, value, nums);
}
}
Related
A logic question in a MOOC I'm taking asked how one would go about returning the total number of increasing subsequences within a given int array using recursion.
In my method I use an index parameter as well as a position parameter to compare values with the index. My regular base case is when the index has reached the end of the list, and then I return 1 to account for an array of length 0 to technically count as a valid increasing subsequence. The method in the else statement I currently have written is only able to find subsequences of length 2. For example, if I have array [1, 2, 3], the method only returns 7 because it isn't counting 123. I'm not sure how to write this so as to account for longer subsequences. I believe it has something to do with creating a separate array and adding values to it and then adding its length to the final value, but I'm not sure how this would be implemented recursively.
public static int bettersubseq(int[] arr, int index, int pos) {
if (index == arr.length) {
return 1;
} else {
if (pos == index) {
return 1 + bettersubseq(arr, index + 1, 0);
} else {
if (arr[pos] < arr[index] && (pos < index)) {
return 1 + bettersubseq(arr, index,pos + 1);
} else {
return 0 + bettersubseq(arr, index, pos + 1);
}
}
}
}
I've got a task that gets an int value "n" and an Int Array as parameters and is supposed to return a boolean.
The method is supposed to determine, how many "n" are in the given Array. If the number is even the method should return true, else false. If the Array has the length 0, it should return "false" aswell.
What i managed to do is :
public static boolean evenNumberOf(int n, int[] arr) {
boolean result = false;
System.out.println("Starting count");
if (n < arr.length) {
if (arr[n] == n) {
result = true;
} else {
return evenNumberOf(n - 1, arr);
}
}
return result;
}
Im just really confused and i dont know what to do to be honest. I have really tried my best but the longer i work on this task the less i understand.
Any help is appreciated and thank you in advance! :)
Separate it into two methods:
The method you call initially
and a method that gets called recursively to count the number of ns in the array:
boolean evenNumberOf(int n, int[] arr) {
int count = countNs(n, arr, 0);
// Logic to choose what to return based on count and/or length of arr.
}
int countNs(int n, int[] arr, int i) {
// Check if arr[i] is equal to n.
// Make a recursive call to countNs for i := i + 1.
// Combine the check/recursive call result to return a value.
}
Try
//arr should not be empty, index and count >= 0
public static boolean evenNumberOf(int value, int index,int[]arr, int count) {
if(index >= arr.length) return count%2 == 0;
if(arr[index] == value ) {
count++;
}
return evenNumberOf(value, ++index, arr, count);
}
Usage example: System.out.println(evenNumberOf(2, 0, new int[]{2,0,3,7,6,11,1,2}, 0));
(You can add an helper method evenNumberOf(int value,int[]arr))
as Recursive Counting in an Array got closed as a duplicate I will answer it here:
Let's analyze what you did and why it's wrong
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
System.out.println("MATCH");
count++;
return count;
}
Here you already return the count when you get a match. You shouldn't do that because if the first number is already the same it returns 1. all you need to do is increase the count here
else {
System.out.println("Moving on");
i = i + 1;
countN(n,arr,i, count);
}
Here you do the recursion. This is good. But this also needs to be done in the case that you do get a match. And it needs to return that value. But, also this only needs to be done when you are not at the end of the array yet
if (arr.length == i) {
evenNumberOf(n,arr);
}
this part doesn't make sense, because you call evenNumberOf with the exact same arguments as it started so it will result in an infinite loop. you should have returned the count here. also keep in mind that the last index of an array is length - 1
putting this together you can make:
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
count++;
}
if (arr.length - 1 == i) {
return count;
}
return countN(n, arr, i + 1, count);
}
I need to figure out how to determine recursively if there is a selection of elements such that the sum of the selected elements is the same as the sum of unselected elements given a list of integers.
So for example the set
nums = [1,3,5,3] returns true because the subsets can be [3,3] and [1,5] that is both lists add up to 6, so the method should return true. If that subsets aren't present it should return false.
I have the code:
private static boolean canFind(int[] nums, int index, int sumOne, int sumTwo) {
if (index == nums.length) {
return false;
}
if (oneSum == twoSum) {
return true;
}
if (oneSum < twoSum) {
return canFind(nums, index + 1, sumOne + nums[index], sumTwo);
}
return canFind(nums, index + 1, sumOne, sumTwo + nums[index]);
}
but I can't figure out why this doesn't work, or even why it would.
The idea of the recursive canFind() method is:
If I have processed the numbers up to position index, and have
collected two sums sumOne and sumTwo so far, is it possible to
find a solution with the remaining numbers?
Before looking at your code in detail, let's clarify the task a little more (if I understand it correctly): For a valid solution, each number has to be counted, either in sumOne or in sumTwo. Skipping a number or counting a number in both sums isn't allowed.
So, at any point in the solution process, you have the choice whether to add the current number in sumOne, or in sumTwo, and that's what you correctly do in the two recursive calls
canFind(nums, index + 1, sumOne + nums[index], sumTwo)
and
canFind(nums, index + 1, sumOne, sumTwo + nums[index])
But there's a problem around the calls. You can't know whether adding the current number to sumOne or sumTwo will be correct for the solution, so you should try both ways and return true if one of them succeeds. Your code adds to sumOne if that's smaller, otherwise to sumTwo. Although this seems plausible, it doesn't necessarily lead to the solution. So, you should change that part to read
if (canFind(nums, index + 1, sumOne + nums[index], sumTwo)) {
// if there's some solution by adding to sumOne, we're finished.
return true;
} else if (canFind(nums, index + 1, sumOne, sumTwo + nums[index])) {
// if there's some solution by adding to sumTwo, we're finished.
return true;
} else {
// if both tries didn't succeed, thre's no solution
// starting from the given situation
return false;
}
How long do we have to continue trying numbers? Until we get to the end of the array, as we're not allowed to leave out any number.
And when we reach the end of the array, do we have a solution or not? It's a solution if both sums are equal.
So, before trying the recursive calls, we should check for the end of the array:
if (index == nums.length) {
if (sumOne == sumTwo) {
return true;
} else {
return false;
}
}
Putting it all together:
private static boolean canFind(int[] nums, int index, int sumOne, int sumTwo) {
if (index == nums.length) {
// if we're at the end of the array, we can compare the sums
// to decide whether this is a solution.
if (sumOne == sumTwo) {
return true;
} else {
return false;
}
}
if (canFind(nums, index + 1, sumOne + nums[index], sumTwo)) {
// if there's some solution by adding to sumOne, we're finished.
return true;
} else if (canFind(nums, index + 1, sumOne, sumTwo + nums[index])) {
// if there's some solution by adding to sumTwo, we're finished.
return true;
} else {
// if both tries didn't succeed, thre's no solution
// starting from the given situation
return false;
}
}
This should basically do the job.
I am trying to write a method where I can find the index of the desired number using binary search and recursion only. This is the method that I wrote:
public static int binSearch_r (int[] data, int value, int from, int to)
{
if (from <= to)
{
int middle = (from+to)/2;
if (data[middle] > value)
{
binSearch_r(data, value, from, middle - 1);
}
else if (data[middle] < value)
{
binSearch_r(data, value, middle+1, to);
}
else
{
return middle;
}
}
return -1;
}
data is the original array that is inputed, value is the number I am trying to find, from is the left most index of the array and to is the right most index of the array.
The array that I tested this method with is simply {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}. However, when I set value to 9, the initial "from" to 0 and the initial "to" to array.length-1, I receive -1 instead of the desired index. This happens for any number that I set for value. What am I doing wrong?
If you are unfamiliar with recursion, this is a great resource that explains it well within a Java context.
In a recursive binary search, the recursive method will reduce the search space if it cannot find the correct index. With the reduced search space the method will call itself to find the index within this reduced space. Each recursive call expects a value to be returned.
public static int binSearch_r (int[] data, int value, int from, int to) {
if (from <= to) {
int middle = (from+to)/2;
if (data[middle] > value) {
return binSearch_r(data, value, from, middle - 1);
} else if (data[middle] < value) {
return binSearch_r(data, value, middle+1, to);
}
return middle;
}
return -1;
}
(Shifted from comment to answer question)
def bs(array,target_value,i,j):
# here i is initial postion and j is last position of array
mid=(i+j)//2
if array[mid]==target_value:
return mid
if array[mid]>target_value:
j=mid-1
return bs(array,target_value,i,j)
if array[mid]<target_value:
i=mid+1
return bs(array,target_value,i,j)
array=[1,2,3,4,5,6,7]
x=bs(array,7,0,7)
print(x)
This is the original problem:
Write a recursive, int valued method named productOfOdds that accepts an integer array and the number of elements in the array, and returns the product of the odd-valued elements of the array. You may assume the array has at least one odd-valued element. The product of the odd-valued elements of an integer-valued array recursively may be calculated as follows:
If the array has a single element and it is odd, return the value of that element; otherwise return 1.
Otherwise, if the first element of the array is odd, return the product of that element and the result of finding the product of the odd elements of the rest of the array; if the first element is NOT odd, simply return the result of finding the product of the odd elements of the rest of the array.
This is what I have and I can't figure out why it's not working:
public static int productOfOdds(int[] arr, int index)
{
if (index == 1)
{
if ((arr[0]%2) != 0)
return arr[0];
else
return 1;
}
else if ((arr[0] % 2) != 0)
return (arr[0] * productOfOdds(arr, index - 1));
else
return productOfOdds(arr, index - 1);
}
The problem is that, while you pass in your index, you don't check the array value at your index, but the array value at 0. This should fix the problem:
public static int productOfOdds(int[] arr, int index){
if (index == 1)
{
if ((arr[index-1]%2) != 0)
return arr[index-1];
else
return 1;
}
else if((arr[index-1]%2) != 0 )
return (arr[index-1] * productOfOdds(arr, index-1));
else
return productOfOdds(arr, index-1);
}
I believe for this part:
else if ((arr[0] % 2) != 0)
return (arr[0] * productOfOdds(arr, index - 1));
You meant to say:
else if ((arr[index] % 2) != 0)
return (arr[index] * productOfOdds(arr, index - 1));
By using 0 here instead of index your result will always be
1 if arr[0] is even
arr[0] if it is odd
The reason it is not working is that you never calculate anything that's not the first array element. There is nothing in your recursion that causes it to go to the second element, the third and so on.
What may be confusing is the fact the parameter that expresses the length of the array is called index. But you're treating it like length. Anyway, let's see what you are doing here:
Your end condition seems good - if the length is 1, test the only element that exists, and do as the assignment text tells you to do.
But what about the recursion step?
Suppose you have two elements and the first one is odd. Your index is 2. So you call the same function with the same array and 1. This will return the value of the element in position zero. And then you multiply it by the element at position zero. If your array was 8 elements long, it would still be multiplying by the same first element, so you basically get (arr[0])length (if it's odd) or 1 (if it's not odd).
You have two ways to solve this problem.
Go with only one parameter, but against the text of the assignment
To do this, you have to check the last element of the array. So if your array length 1, you do as you did so far. But if it's greater than 1, you have to do:
if ( arr[index-1]%2 != 0 ) {
return arr[index-1]*productOfOdds(arr,index-1);
} else {
return productOfOdds(arr,index-1);
}
Go with two parameters, but follow the letter of the assignment
To do this, you have to also pass the parameter that says where the subarray starts. That is, you check the first element of the array, but tell the recursive step to check from the second element forward. Basically, you tell your method "Look at this array as if it's starting at position startIndex rather than 0".
private static int productOfOdds(int[] arr, int startIndex, int length) {
if (length == 1) {
if ((arr[startIndex]%2) != 0)
return arr[startIndex];
else
return 1;
} else if((arr[startIndex]%2) != 0 )
return (arr[startIndex] * productOfOdds(arr, startIndex + 1, length-1));
else
return productOfOdds(arr, startIndex+1, length-1));
}
public static int productOfOdds(int[] arr, int length ) {
return productOfOdds( arr, 0, length );
}
The second method with just two parameters is there in order to follow the letter of your assignment, which was to have a method that accepts an array and its length only. Internally it works with three parameters, but to the world you present a two-parameter method (note the private vs public modifiers).
Personally, I think the first method is more elegant, despite the fact that your instructor told you to use the first element.