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 got a partition problem for which I need advice. I'm given a 1D array whose length is even. I need to write a boolean method to determine whether the array can be divided into 2 equally sized subarrays with equal sum, no loops are allowed.
For example, array #1 {-3,5,-12,14,-9,13} will return false, because -3 + 5 -12 + 14 = -9 + 13, however on the left side there are 4 elements and on the other side 2.
array #2 will return true:
{-3,14,12,5,-9,13} : -3 + 5 + 14 = 12 - 9 + 13
Here's what I've done so far:
public static boolean canBeDividedEqually(int[] arr)
{
if (arr.length %2 ==0){
return canBeDividedEquallyHelper(arr, 0, 0, 0);
}
return false;
}
public static boolean canBeDividedEquallyHelper(int[] arr, int i, int sum1, int sum2)
{
if (i == arr.length){
return sum1 == sum2;}
return canBeDividedEquallyHelper(arr, i+1, sum1 + arr[i], sum2) ||
canBeDividedEquallyHelper(arr, i+1, sum1, sum2 + arr[i]);
}
For case #2, it will return true as expected, but for case #1 it will also return true. I need to add a condition that will disqualify an array of type case #1.
You were almost there. In addition to the sums, pass the number of elements:
public class Solver
{
public static boolean canBeDividedEqually(int[] arr)
{
return canBeDividedEquallyHelper(arr, 0, 0, 0, 0, 0);
}
public static boolean canBeDividedEquallyHelper(int[] arr, int i, int nb1, int sum1, int nb2, int sum2)
{
if (i == arr.length)
return nb1 == nb2 && sum1 == sum2;
return canBeDividedEquallyHelper(arr, i+1, nb1+1, sum1 + arr[i], nb2, sum2) ||
canBeDividedEquallyHelper(arr, i+1, nb1, sum1, nb2+1, sum2 + arr[i]);
}
public static void main(String[] args)
{
System.out.println(canBeDividedEqually(new int[]{-3, 5, -12, 14, -9, 13})); // false
System.out.println(canBeDividedEqually(new int[]{-3, 14, 12, 5, -9, 13})); // true
}
}
Try this.
static boolean canPartitioning(int[] arr) {
return new Object() {
int length = arr.length, half = length / 2;
boolean partition(int i, int selected, int sum, int rest) {
if (i >= length)
return selected == half && sum == rest;
return selected < half && partition(i + 1, selected + 1, sum + arr[i], rest)
|| partition(i + 1, selected, sum, rest + arr[i]);
}
}.partition(0, 0, 0, 0);
}
public static void main(String[] args) {
System.out.println(canPartitioning(new int[] {-3, 5, -12, 14, -9, 13}));
System.out.println(canPartitioning(new int[] {-3, 14, 12, 5, -9, 13}));
}
output:
false
true
Here's a solution without using loops,
static int[] arrA, arrB;
public static boolean equalSplit(int[] arr) {
//Step 1
if (arr.length % 2 == 0) {
int sumA = 0, sumB = 0; // Two int variables to store the value of sum.
// Initializing the two new arrays with equal length.
arrA = new int[arr.length / 2];
arrB = new int[arr.length / 2];
// Copying the elements from the given array to the new arrays.
arrA = createArray(arrA, 0, arr, 0);
arrB = createArray(arrB, 0, arr, arr.length / 2);
//Calculating and storing the sum in the variables.
sumA = arraySum(arrA, arrA.length);
sumB = arraySum(arrB, arrB.length);
return sumA == sumB; // Checking the codition
} else {
return false;
}
}
private static int[] createArray(int[] arr, int index, int[] copyFrom, int copyFromIndex) {
if(index == arr.length) return arr;
arr[index] = copyFrom[copyFromIndex];
index++;
copyFromIndex++;
return createArray(arr, index, copyFrom, copyFromIndex);
}
private static int arraySum(int[] arr, int N) {
if (N <= 0) return 0;
return (arraySum(arr, N - 1) + arr[N - 1]);
}
My approach towards this question is,
Step 1 -> Checking whether can you split the given array into two equal arrays. If yes next comes the Step 2 or return false without any further steps.
Step 2 -> Copying the given array elements into two different but equal arrays using recursion.
Step 3 -> Sum the newly populated two arrays and store it in two different variable.
Step 4 -> If the Sum of both the newly populated arrays is equal then the function return true else false.
Explanation :
Create two new integer arrays which are going to get populated only if the given array can be divided into two equal parts. Here it is arrA and arrB.
Check whether if the length of given array can be divided by two and have 0 remainders because this can give the answer to the question "Can this array be divided into two equal parts ?". The piece of code in this answer is arr.length % 2 == 0. If the given array satisfies this condition only then the steps given below will be carried out else it will return false.
Initialize two integer variable to store the value of Sum of both the equally divided arrays.
Initialize the two newly created arrays with the array length of half the given array which is arr.length / 2.
Then copy first half of given array elements to the first newly initialized array then the second half to the second array. To achieve this createArray(int[] arr, int index, int[] copyFrom, int copyFromIndex) method is used. arr is the argument to pass the array which should be copied to, index should be 0 because it is used as the index of newly created arrays, copyFrom is a parameter for the given array which has all the elements, copyFromIndex is used to start copying the elements from the given index.
Then calculate the sum using recursive function and store it in separate variable which was created earlier. The function used here was arraySum(int[] arr, int N).
Return whether both the sum variables are equal.
If the change of elements order is allowed, you have to check every possible permutation of the array:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {-3, 5, -12,14,-9,13};
int[] b = {-3,14, 12, 5,-9,13};
System.out.println(isEquallySplittable(a));
System.out.println(isEquallySplittable(b));
}
public static boolean isEquallySplittable(int[] array){
long arraySum = arraySum(array);
if(arraySum % 2 != 0) return false; //can not split an even sum by half
return isEquallySplittable(array, 0, 0, arraySum);
}
public static boolean isEquallySplittable(int[] array, int indexFrom, int indexTo, long sumArray){
if(indexTo == indexFrom) {
indexTo++;
}
if(indexTo >= array.length) {
indexTo = 0;
indexFrom++;
}
if(indexFrom >= array.length) return false;
long sumHalfArray = arraySum(Arrays.copyOf(array, array.length/2)); //sum first half of the array
if(sumArray == sumHalfArray * 2 ){
System.out.println(Arrays.toString(array) + " can be split into 2 equal arrays");
return true;
}
//next permutation
int temp = array[indexTo];
array[indexTo] = array[indexFrom];
array[indexFrom] = temp;
return isEquallySplittable(array, indexFrom, ++indexTo, sumArray);
}
public static long arraySum(int[] arr) {
return arraySum(arr, 0, 0);
}
private static long arraySum(int[] arr, int index, long sum) {
if (index >= arr.length ) return sum;
sum += arr[index++];
return arraySum(arr,index,sum);
}
}
Here is Recursive solution in which elements need not be consecutive. This is simple recursive approach in which we take two lists named list1 and list2 respectively.
Then we check if it is possible to obtain a solution by adding this element in list1 (means nums[index] in context of program) if not it will check by adding the same in list2.
When the condition being true the the function recursively add element to respective list and if no solution is possible then function returns false.
The time complexity of the solution is O(2^n) as function tries each possible combination of elements adding to lists.
Here is code:
Example: int nums[] = new int[]{1, 1, 3, 4, 7};
For this resulting output would be [4, 3, 1] & [7, 1] order of elements get changed due to recursive calls.
import java.util.ArrayList;
public class SumPartition {
/**
* These are list that stores possible sum arrays
*/
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
public static void main(String[] args) {
int[] arr = new int[]{1, 1, 3, 4, 7};
SumPartition sumPartition = new SumPartition();
if(sumPartition.sameSumArrays(arr, 0, 0, 0)) {
System.out.println(sumPartition.list1);
System.out.println(sumPartition.list2);
}
else {
System.out.println("This is not possible");
}
}
/**
*
* #param nums is array of numbers
* #param index is index of nums array
* #param sum1 is sum1 which is sum of elements in list1
* #param sum2 is sum2 which is sum of elements in list2
*/
public boolean sameSumArrays(int nums[], int index, int sum1, int sum2) {
if(index == nums.length) {
return sum1 == sum2;
}
if(sameSumArrays(nums, index+1, sum1+nums[index], sum2)) {
list1.add(nums[index]);
return true;
}
else if(sameSumArrays(nums, index+1, sum1, sum2+nums[index])) {
list2.add(nums[index]);
return true;
}
return false;
}
}
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'm quite new to Java so please bear with me. I wrote this program:
public static void main(String args[])
{
int[] list = {1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 10};
isUnique(list);
System.out.println(isUnique(list));
}
private static boolean isUnique(int[] array)
{
int count = 0;
for (int n : array)
{
for (int i = 0; i < array.length; i++)
{
if (n == array[i])
{
count++;
}
if (count > 1)
{
return false;
}
else
{
return true;
}
}
}
return false;
}
}
It's supposed to check the array and see, if there are any more than 1 of each number. However it doesn't seem to work. It returns true even if there are two 1's. Any ideas? I suspect the for loop isn't working, but I'm not quite sure why.
Thanks in advance!
It returns true no matter what because you have that else block. Because count starts up zero and it increases a maximum of one time per loop, that else block will always run (if the array length is not 0). You can think of this as two cases:
Case 1. n == array[i] --> count will equal 1 --> count>1 is not true --> else block runs and returns true.
Case 2. n is not array[i] --> count equals 0 --> count>1 is not true --> else block runs and returns true
Your code returns true after checking the first element, since after checking the first element count == 1, so your else statement is executed :
if (count > 1)
{
return false;
}
else
{
return true;
}
You should only return true after checking all the elements in your array and finding no duplicates.
If the input array is sorted, you don't need a nested loop to determine if there are two consecutive equal numbers. A single loop will do.
If the array is not sorted, you'll have to maintain a count for the number of occurrences of each value found in the array, for which purpose a HashMap can be used.
Assuming sorted input array :
private static boolean isUnique(int[] array)
{
if (array.length <= 1)
return true;
int previous = array[0];
for (int i = 1; i < array.length; i++)
{
if (previous == array[i])
{
return false;
}
previous = array[i];
}
return true;
}
For example if I have an array of ints as a parameter to my method, my method needs to return an array of ints where each element is the sum of all the elements following it.
Example:
parameter is [5, 6, 7, 2, 3, 1] I need to return [24, 19, 13, 6, 4, 1]
I have a written a helper method that correctly adds an index to all of the ones after it here:
public static int sum(int[] array, int index) {
if (index == array.length) {
return array[array.length-1];
} else {
return array[index] + sum(array, index + 1);
}
}
This all works as it should, but I'm having trouble with the original method here:
public int[] reverseCumulative(int[] numbers) {
int[] temp = new int[numbers.length];
if (numbers.length == 0) {
return temp;
}
else {
temp[numbers.length-1] = sum(numbers, numbers.length);
numbers = Arrays.copyOf(numbers, numbers.length - 1);
reverseCumulative(numbers);
return temp;
}
}
The output here is [0, 0, 0, 0 , 0, 1]. I understand that this is most likely due to the fact I'm creating a new int[] temp every time I call the reverseCumulative method within itself, but I am completely lost and any push in the right direction would be appreciated.
Edit: Forgot to add, I am not allowed to use any loops.
Since you are creating a new array each time you call the reverseCumulative method, you should use the sum method as a helper method inside the reverseCumulative method so that you are still using recursion. For example,
public int[] reverseCumulative(int[] numbers) {
int[] temp = new int[numbers.length];
if (numbers.length == 0) {
return temp;
}
else {
for(int i = 0; i < numbers.length; i++){
temp[i] = sum(numbers,i);
}
return temp;
}
}
This way, each element in temp equals a sum of integers in the numbers array depending on which iteration it is currently on. In the first iteration, temp[0] = the sum of all the ints in numbers. In the second iteration, temp[1] = the sum of all the ints in numbers except the first int and so on. However, the way the sum method is written right now, it adds the last element twice so here's a simple fix,
public static int sum(int[] array, int index) {
if (index == array.length-1) {
return array[array.length-1];
} else {
return array[index] + sum(array, index + 1);
}
}
Maybe something like this?
public static int sum(final int[] target, final int[] source, int index) {
if (index >= source.length - 1)
return source[index];
return target[index] = source[index] + sum(target, source, index + 1);
}
public static int[] reverseCulmulative(final int[] array) {
final int[] target = array.clone();
sum(target, array, 0);
return target;
}