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);
}
}
}
}
Related
I am getting true as answer even for unsorted(isNonDescending) arrays. Where is the bug?
I want to break the array into smaller problem from the start of the array only.
//Check for isNonDescending.
public class AlgoAndDsClass {
public static void main(String args[]) {
int[] unsortedArry = { 1, 2, 3, 4 };
int[] unsortedArry2 = { 1, 2, 4, 3 };
System.out.println(isSorted(unsortedArry, unsortedArry.length));
System.out.println(isSorted(unsortedArry2, unsortedArry2.length));
}
private static boolean isSorted(int[] arr, int size) {
if (size == 0 || size == 1)
return true;
if (arr[0] > arr[1]) {
return false;
}
System.out.println(arr.length);
boolean smallwork = isSorted(arr, size - 1);
return smallwork;
}
Instead of passing the size of the array as a parameter, which makes no sense anyway, because you can simply call arr.length, you should pass a starting index and increase it with each recursive call until you have reached the length of your array.
private static boolean isSorted(int[] arr, int index) {
if(arr.length == 0 || arr.length == 1 || index == arr.length - 1){
return true;
}
if (arr[index] > arr[index + 1]) {
return false;
}
return isSorted(arr, index + 1);
}
and call from main with 0 as a starting index
System.out.println(isSorted(unsortedArry,0));
System.out.println(isSorted(unsortedArry2,0));
you keep on checking the same 2 elements, try using the size variable instead as the arrray indexes.
For exmaple, if the first 2 elements are sorted you'll get true, thats because you check only the first two elements in the arrray.
Array is sorted if the sub-array from the start and up to one element before last is sorted and the last element is larger or equal to the element before last one.
Let's assume I have this array: ARR = {5, 7, 3, 3, 7, 5}
and I also have the size ( = 6 in this example ) so the recursive function should return 3.
this is the declaration of the function/method:
int f(arr, size);
I tried this thing:
count = 0;
if(size == 1)
return 1;
if(x[i] != f(arr, size-1)
count++;
return count;
but it doesn't work, as f(arr, size-1) doesn't walk through all the elements of the array and compare.
hopefully you guys could help!
Here's one way to do it:
private static int f(int[] arr, int size) {
if (size <= 1) return 0; // there can't be duplicates if there are not even 2 elements!
return f(arr, size - 1) + (inArray(arr, size - 1, arr[size - 1]) ? 1 : 0);
}
private static boolean inArray(int[] arr, int size, int elem) {
if (size == 0) return false;
return arr[size - 1] == elem || inArray(arr, size - 1, elem);
}
Basically the logic is this:
The size indicates the first N elements in arr that we actually care about.
If size is less than 2, we know there can't be any duplicates, so return 0.
Now for the recursion case, we return either 1 or 0 depending on whether the last element is in the rest of the array, plus whatever number of duplicates in the rest of the array ("the last element" means array[size - 1] and "the rest" means calling the function with size - 1.)
To determine whether an element is in an array, I used a recursive method as well, with a similar idea (check if the last element is elem, then check if the rest contains elem).
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.