How to manage recursive function? - java

I need to write a recursive function that gets 4 parameters.
The 1st one is array. the 2nd one - left index, the 3rd one a right index and "K" index. "K" index is a cell in array , and the lrft index points to the start and the right one points to the end.
An array may contain such digitalis as zeros and ones. The method returns the maximum length of a sequence of ones that contain the cell k.
Here the example of the result that I need to get:
public static void main(String[] args) {
int[] A = {1,1,1,0,1,1,0,1,1,1,1,1,0,1,1};
System.out.println(floodOnes(A,0, A.length-1, 9)); // 5 output
System.out.println(floodOnes(A,0, A.length-1, 3)); // 0 output
System.out.println(floodOnes(A,0, A.length-1, 0)); // 3 output
System.out.println(floodOnes(A,0, A.length-1, 14)); // 2 output
}
public static int floodOnes(int [] A,int left, int right, int k){
//some logic
}
Here is my implementation:
public class Program {
public static void main(String[] args) {
int[] A = {1,1,1,0,1,1,0,1,1,1,1,1,0,1,1};
System.out.println(floodOnes(A,0,A.length-1, 9));
}
public static int floodOnes(int [] A,int left, int right, int k){
if (left != k) left+=1;
if (right != k) right-=1;
if (left == k && right == k) return A[k]; //condition when the recursive call stops
int res = floodOnes(A, left, right, k);
if (A[left] == 1 && A[right] == 1)
return res = A[left] + A[right]; //count ones
else return res;
}
}
But my solution not working properly.
In this rows:
if (A[left] == 1 && A[right] == 1)
return res = A[left] + A[right]; //count ones
If one of the conditions isn`t executed once, the following returns shouldn't add ones to result variable.
And I don't know how to do it.

I proved my comment wrong. Here is a recursive method with the 4 parameters mentioned in the question that indeed solves the problem.
public static int floodOnes(int[] a, int left, int right, int k) {
if (0 <= left && left <= k && k <= right && right < a.length) {
// is there a 0 between left (inclusive) and k (exclusive)?
int i = left;
while (i < k && a[i] == 1) {
i++;
}
if (i < k) {
assert a[i] == 0;
return floodOnes(a, i + 1, right, k);
}
// is there a 0 between k (exclusive) and right (inclusive)?
i = right;
while (i > k && a[i] == 1) {
i--;
}
if (i > k) {
assert a[i] == 0;
return floodOnes(a, left, i - 1, k);
}
// no zero found, a[k] not checked, though
if (a[k] == 0) {
return 0;
} else {
return right - left + 1;
}
} else {
throw new IllegalArgumentException("Expected " + left + " <= " + k + " <= " + right + " < " + a.length);
}
}
With this method, the first main method in your question prints the expected:
5
0
3
2
I really don’t see a point in solving the problem in this way, so I am far from sure this was what was intended. I’d prefer a non-recursive solution, or if it just needs to be recursive somehow, then the solution in Grzegorz Górkiewicz’ answer.

You can decompose this problem into 2 functions.
The first will count elements on the left-hand side, the latter on the right-hand side. Both use recursion.
public static int floodOnes(int[] A, int left, int right, int k) {
return checkLeft(A, left, k-1, A[k]) + 1 + checkRight(A, right, k+1, A[k]);
}
public static int checkLeft(int[] A, int leftBoundary, int k, int number) {
if (k < 0 || A[k] != number || k < leftBoundary)
return 0;
return 1 + checkLeft(A, leftBoundary, k-1, number);
}
public static int checkRight(int[] A, int rightBoundary, int k, int number) {
if(k >= A.length || A[k] != number || k > rightBoundary)
return 0;
return 1 + checkRight(A, rightBoundary, k+1, number);
}
I assume:
that 0 <= left <= k <= right < A.length;
that the solitary number should be counted as 1 (sequence of length 1) unlike your example. If you want it to be counted as 0, add if(A[k] != 1) return 0; or a similar condition in your floodOnes method.
Therefore:
System.out.println(floodOnes(A, 0, A.length - 1, 9)); // prints 5
System.out.println(floodOnes(A, 0, A.length - 1, 3)); // prints 1
System.out.println(floodOnes(A, 0, A.length - 1, 0)); // prints 3
System.out.println(floodOnes(A, 0, A.length - 1, 14)); // prints 2
Besides left and right parameters can be used for some input exceptions
(e.g. k > A.length).

Since you are looking for - the maximum length of a sequence of ones that contain the cell k. A simple and concise code to achieve this can be as follows.
public static void main(String[] args) {
int[] A = {1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1};
System.out.println(floodOnes(A, 0, A.length - 1, 9)); // prints 5
System.out.println(floodOnes(A, 0, A.length - 1, 3)); // prints 0
System.out.println(floodOnes(A, 0, A.length - 1, 0)); // prints 3
System.out.println(floodOnes(A, 0, A.length - 1, 14)); // prints 2
}
public static int checkLeft(int[] A, int k) {
return (k < 0 || A[k] != 1) ? 0 : 1 + checkLeft(A, k - 1);
}
public static int checkRight(int[] A, int k) {
return (k > (A.length - 1) || A[k] != 1) ? 0 : 1 + checkRight(A, k + 1);
}
public static int floodOnes(int[] A, int left, int right, int k) {
return (A[k] != 1) ? 0 : checkLeft(A, k - 1) + 1 + checkRight(A, k + 1);
}
It outputs the desired result.
5
0
3
2

Related

longest Flat Sequence - recursion problem

First of all I'm a beginner programmer and I'm pretty sure I have quite a few errors in the code.
I'm stuck in code in the exercise,
sequence flat of integers if all the numbers in it are the same number or the series consists of two consecutive number,
I need to write a recursive method which receives an array of integers, and returns the length of the maximum subset which is a flat series.
For example for this array:
(4, 5, 6, 5, 4, 3)
The method will return 3. Since the sub-arrays that make up the flat series in the array are:
(4, 5) - Length 2.
(5, 6, 5) - Length 3.
(5, 4) - Length 2.
(4, 3) - Length 2.
The longest flat sub-series in the array is 3 in length, which is the value to be returned.
public static int longestFlatSequence (int[] arr)
{
return lengthFlat (arr, 0, 0);
}
private static int lengthFlat (int[] arr, int i, int max)
{
if (arr.length >= 1)
{
return arr.length;
}
if (i + 1 <= arr.length -1)
{
if (arr[i] == arr[i+1] || arr[i] + 1 == arr[i+1])
{
int val = lengthFlatSequence(arr,i,i+1);
if (val > max)
{
max = val;
}
}
return lengthFlat(arr, i+1, max);
}
return max;
}
private static int lengthFlatSequence(int[] arr, int i, int curr)
{
if (i == arr.length - 1)
{
return curr;
}
int min = 0;
if (arr[i] < arr[i+1])
{
min = arr[i];
}else{
min = arr[i+1];
}
if (min == arr[curr] || min + 1 == arr[curr])
{
return lengthFlatSequence(arr, i, curr);
}else{
return curr;
}
}
Please help me fix the code.
Thank you!

Reduce the array to 0 in minimum moves with given constraints

You are given a city which lies on the x-axis. It has n buildings. The first building lies in x = 1 and has height h1, the second building lies on x = 2 and has height h2 and so on. You are a gigantic monster with a sword who wants to destroy the city. You are also a computer scientist at heart so you efficiency is the key, hence you want to destroy the city using minimum number of moves.
You can make one of the two moves :
1. Make a horizontal cut from x = L to x = R, cutting down the heights of the buildings from x = L to X = R by 1.
2. make a vertical cut at x = P, completely destroying the building at x = P thereby making its height zero.**
Note that : for the 1st type of move, every city in the range from L to R must have at least 1 height remaining, i.e. you cannot strike through an empty space.
Print the minimum number of moves needed to destroy the city.
Input
First line contains the number of test cases.
For each test case, the first line contains the number of buildings n.
Second line contains n integers denoting the heights of the building
Output
For every test case, print the minimum number of moves to destroy the city on a new line.
Notes
1 ≤ n ≤ 1000
0 ≤ hi ≤ 1000
Sample Input 0
2
5
2 2 2 3 3
5
10 2 10 2 10
Sample Output 0
3
5
I cannot figure out the approach to the question.
My code does not work for the following input:
1 1 1 2 4 5 7 7 8 9**
In my code i reduce the min value from all elements. Then find out the subarray between zeros and then compare the length of subarray(j-i) with the minimum value. if the length is less, then then we need to follow move 2, else move 1.
My code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.Scanner;
public class Main {
static int findmin(int arr[], int i, int j) {
int min = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
if (min > arr[k]) {
min = arr[k];
}
}
return min;
}
static void subtractmin(int arr[], int i, int j, int min) {
//if both the length of subarray and min are equal, we destroy separately
if (j - i <= min) {
for (int k = i; k < j; k++) {
// if
arr[k] = 0;
}
} else {
//subtract all
for (int k = i; k < j; k++)
// if
{
arr[k] -= min;
}
}
}
public static void main(String[] args) {
//int input[] = {10, 2, 10, 2, 10};// 5
//int input[] = {2, 2, 2, 3, 3};// 5
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- != 0) {
int zeros = 0;
int n = sc.nextInt();
int input[] = new int[n];
int min = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
input[i] = sc.nextInt();
if (min > input[i]) {
min = input[i];
}
if (input[i] == 0) {
zeros++;
}
}
//subtract minimum element from array
int count = 0;
if (zeros == 0) {
count += min;
subtractmin(input, 0, n, min);
} else {
count += min;
subtractmin(input, 0, n, min);
}
//traverse the array and findsubarrays between 0's
//1) if an element is surrounded by 0's it will be destroyed at once separately
// 2) also if length of subarray<min element, they all need to be destroyed separately
// 3) if min<length of subarray they need to be destroyed at once with count+=min
int i = 0, j = 0;
while (true) {
//move i to the first non zero element
for ( i = 0; i < n; i++) {
if (input[i] != 0) {
break;
}
}
//means whole array is 0;
if (i == n) {
System.out.println(Math.min(count, n - zeros));
break;
}
///start with the first non zero element and fin
for (j = i; j <= n; j++) {
if ( j == n || input[j] == 0) {
// take out min element
int minEle = findmin(input, i, j) ;
//if min lement is greater than subarray size, destroy separately
count += Math.min(minEle, j - i);
//System.out.println("count="+count+"min element="+minEle);
// subtract minimum element
subtractmin(input, i, j, minEle);
}
//if last elemnt is not zero
}
}
}
}
}
A possible hint here is that reducing a building to zero separates sections, which implies divide and conquer.
Let f(A, l, r) represent the optimal number of moves for the section of A indexed at [l, r]. Then:
f(A, l, r):
min(
# Reduce the whole section
# without separating it, using
# move 1, the horizontal cuts.
max(A[l..r]),
# Divide and conquer
1 + f(A, l, k-1) + f(A, k+1, r)
)
for all l ≤ k ≤ r
Except we don't need to try all ks, just one that points to max(A). Not removing max(A) implies we would need to either perform max(A) moves or we would have to remove it later.
JavaScript code:
function findMax(A, l, r){
let idx = l;
for (let i=l; i<=r; i++)
if (A[i] > A[idx])
idx = i;
return idx;
}
function f(A, l=0, r=A.length-1, memo={}){
if (l > r)
return 0;
if (l == r)
return 1;
const key = String([l, r]);
if (memo.hasOwnProperty(key))
return memo[key];
const k = findMax(A, l, r);
const best = Math.min(A[k], 1 + f(A, l, k-1, memo) + f(A, k+1, r, memo));
return memo[key] = best;
}
var As = [
[2, 2, 2, 3, 3],
[10, 2, 10, 2, 10],
[1, 1, 1, 2, 4, 5, 7, 7, 8, 9]
];
for (let A of As)
console.log(f(A));
The probleme you have is not in the code, but in the algorithm. If the size of a segment is small enough, effectivelly you have to perform move 2. However, this condition is not indispensable.
In practice, a simple recursive approach can solve this problem. In a given segment [k, l], after having substracted the min value, you simply have to perform:
n_moves = min (n, vmin + min_moves(x, k, l));
In the following, one function detects positions of the zeros and sum the moves corresponding to each segment
and another function is called for each segment with no zero inside.
The following code is in C++, but it is rather simple and should be easily translated to another language.
Output:
1 2 7 : 3
2 2 2 3 3 : 3
10 2 10 2 10 : 5
1 1 1 2 4 5 7 7 8 9 : 8
This code is provided for completeness. What is important is the algorithm itself.
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> get_zeros (const std::vector<int> &x, int k, int l) {
std::vector<int> zeros;
for (int i = k; i <= l; ++i) {
if (x[i] == 0) zeros.push_back(i);
}
return zeros;
}
int min_moves (std::vector<int> &x, int k, int l);
// This function is called after detection the position of the zeros -> no zero inside
int min_moves_no_zero (std::vector<int> &x, int k, int l) {
int n = l-k+1;
if (n == 0) return 0;
if (n == 1) return 1;
int vmin = 10000;
for (int i = k; i <= l; ++i) {
if (x[i] < vmin) vmin = x[i];
}
for (int i = k; i <= l; ++i) {
x[i] -= vmin;
}
int nm = std::min (n, vmin + min_moves(x, k, l));
return nm;
}
// This function detects positions of the zeros and sum the moves corresponding to each segment
int min_moves (std::vector<int> &x, int k, int l) {
auto zeros = get_zeros (x, k, l);
if (zeros.size() == 0) return min_moves_no_zero (x, k, l);
int start = k;
int total = 0;
for (int z = 0; z < zeros.size(); ++z) {
int end = zeros[z] - 1;
if (start != zeros[z]) {
total += min_moves_no_zero (x, start, end);
}
start = end + 2;
}
if (start <= l) {
total += min_moves_no_zero (x, start, l);
}
return total;
}
void print (const std::vector<int> &x) {
for (auto k: x) {
std::cout << k << " ";
}
}
int main() {
std::vector<std::vector<int>> input {
{1, 2, 7},
{2, 2, 2, 3, 3},
{10, 2, 10, 2, 10},
{1, 1, 1, 2, 4, 5, 7, 7, 8, 9}
};
for (auto& arr: input) {
auto save = arr;
int moves = min_moves (arr, 0, arr.size()-1);
print (save);
std::cout << " : " << moves << "\n";
}
}

Java recursion odd of sum

We have to find sum of array and then return if the value is odd (boolean) using recursion
A = {87, 31, 15, 25, 10, 15, 21, 75)
methodname(A, pos) //position is 0 at the begining
i did this so far, but i'm way off since i can't sum and return boolean in the same line
if (pos == array.length-1) {
return A[pos] % 2 != 0
} else {
if (pos < A.length - 1)
return A[pos] + methodname(A, pos + 1) % 2 == 1;
}
public static void main(String[] args) {
System.out.println(isSumOdd(new int[]{3, 3, 4}, 0));
}
private static boolean isSumOdd(int[] arr, int pos) {
return pos == arr.length - 1
? arr[pos] % 2 != 0
: isSumOdd(arr, pos + 1) ^ arr[pos] % 2 != 0; //Sum of 2 numbers can be odd iff exactly one of them is odd.
}
You can try using the following approach (syntax might be wrong, treat the following as pseudo code):
// gives whether the sum from i to end
// is even or odd
Boolean sumIsEven(int[] arr, int i ){
//base case
if(arr.length-1==i){
return arr[i]%2 ==0;
}
if(arr[i]%2 == 0){
return sumIsEven(arr, i +1);
}else{
// arr[i] is odd
return !sumIsEven(arr, i +1);
}
}
But this will give only if the whole sum is odd/even

Sorting an array, even numbers first, using recursive method. (not working) [duplicate]

I saw this code on this site. It uses a method to sort out an array with even numbers coming out in the front and odd numbers in the back of the array. I was wondering if you could do the same thing except make the odd numbers appear first and then the even numbers afterward? I tried but to no avail. I am new to coding in java and I wanted to test recursion.
public class Recurse {
//i=left
//j=right
//first i tried to shift the whole thing
//have all even numbers pop to the front of array when even
public static int[] seperator(int[] arr1, int left, int right){
int temp;
if(left>=right) //base case, return array
return arr1;
else if(arr1[left]%2!=0 && arr1[right]%2==0){//if match, do the swap
temp=arr1[left];
arr1[left]=arr1[right];
arr1[right]=temp;
return seperator(arr1, left+1, right-1);
}
else{
if(arr1[right]%2!=0){//if right side is on odd #, then decrease index
return seperator(arr1, left, right-1);
}
if(arr1[left]%2==0){//if left side is on even #, then increase index
return seperator(arr1, left+1, right);
}
}
return arr1;
}
public static void main(String[] args){
//int index=0;
int[] arry={70,13,48,19,24,5,7,10};
int[] newarry=seperator(arry, 0, arry.length-1);
System.out.print("The new sorted array is: ");
for(int i=0; i<newarry.length;i++){
System.out.print(newarry[i]+" ");
}
}
}
the output is this:
The new sorted array is: 70 10 48 24 19 5 7 13
Well, if you want the odd numbers to come first, replace any %2!=0 with %2==0 and any %2==0 with %2!=0 :
public static int[] seperator(int[] arr1, int left, int right){
int temp;
if(left>=right)
return arr1;
else if(arr1[left]%2==0 && arr1[right]%2!=0){
temp=arr1[left];
arr1[left]=arr1[right];
arr1[right]=temp;
return seperator(arr1, left+1, right-1);
}
else{
if(arr1[right]%2==0){//if right side is on even #, then decrease index
return seperator(arr1, left, right-1);
}
if(arr1[left]%2!=0){//if left side is on odd #, then increase index
return seperator(arr1, left+1, right);
}
}
return arr1;
}
Try out something like:
public static int[] seperator(int[] arr1, int left, int right) {
int temp;
if (left >= right) // base case, return array
return arr1;
else if (arr1[left] % 2 == 0 && arr1[right] % 2 != 0) {// if match, do the swap
temp = arr1[left];
arr1[left] = arr1[right];
arr1[right] = temp;
return seperator(arr1, left + 1, right - 1);
} else {
if (arr1[right] % 2 == 0) {// if right side is on odd #, then decrease index
return seperator(arr1, left, right - 1);
}
if (arr1[left] % 2 != 0) {// if left side is on even #, then increase index
return seperator(arr1, left + 1, right);
}
}
return arr1;
}
Output:
The new sorted array is: 7 13 5 19 24 48 70 10
public class Program {
public static void main(String[] args) {
int a[] = { 2, 3, 5, 6, 7, 8, 10, 46, 50 };
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0 ; j < a.length-1; j++) {
if (a[j] % 2 != 0) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}

Arrays in Java - Core Java

In This Question A value is "everywhere" in an array if for every pair of adjacent elements in the array, at least one of the pair is that value. Return true if the given value is everywhere in the array.
isEverywhere({1, 2, 1, 3}, 1) → true,coz 1 is present in(1,2) and (1,3)
isEverywhere({1, 2, 1, 3}, 2) → false,coz 2 is in (1,2) but not in (1,3)
isEverywhere({1, 2, 1, 3, 4}, 1) → false,coz 1 is present in 2 pairs (1,2) and (1,3) but 4 is not having a pair of 1
My Partial working code is below,could you help me out with this problem,stuck up for a long time.
::Code::
public boolean isEverywhere(int[] nums, int val) {
boolean flag = false;
for(int i=0;i<nums.length;i++){
for(int j=i+2;j<nums.length;j++){
if(nums[i] == nums[j]){
flag = true;
}
}
}
return flag;
}
Result expected:
`Expected` `This` `Run`
isEverywhere({1, 2, 1, 3}, 1) → true true OK
isEverywhere({1, 2, 1, 3}, 2) → false true X
isEverywhere({1, 2, 1, 3, 4}, 1) → false true X
Try this:
boolean isEverywhere(int[] nums, int val) {
// use i+=2 to get start index of pair.
for(int i=0;i<nums.length;i+=2) {
// other index in the pair.
int j = i + 1;
// make sure the other index really exists.
if(j < nums.length) {
// if it exists..and val is not equal to
// either in the pair..return false.
if(nums[i] != val && nums[j] != val) {
return false;
}
} else {
// no pair..one element case.
// return true if that element is val..else return false.
return nums[i] == val;
}
}
// array has no unpaired element..and all pairs have val.
return true;
}
The key is
for every pair of adjacent elements in the array
Print out i and j before if(nums[i] == nums[j]) and you'd see what's going on.
For an array of length 2, you need (0, 1), for array of length 3, you need (0, 1), (1, 2), and so on.
You never use val in your code
Try figuring out the logic for that first
And this can be done with a single loop, try to figure out how you would as a person apply an algorithm, then code it
Your code is failing because the flag does not turn off in the case that the second loop goes beyond the array length.
Not a full solution, but if the length of the array is odd, check that the last value equals the target val
...
if( !(nums.length % 2) == 0 ){
if( nums[length-1] != val){
return false;
}
}
...
I did mine by simply counting if there are spaces:
Here it is in it's simple glory:
public boolean isEverywhere(int[] nums, int val) {
//Create an int to count the number of spaces between each instance of val.
int counter = 0;
//Create a for loop that checks val;
for (int i = 0; i < nums.length; i++)
{
//If the number at iteration i != val;
if (nums[i] != val)
{
//We increment the counter by one.
counter++;
}
//If the number does equal val, we put the counter back to 0;
else
{
counter = 0;
}
//If the counter is greater than or equal to two,
//We know that there is a space of more than 2, and so
//We return false;
if (counter >= 2)
{
return false;
}
}
//Return true if not false;
return true;
}
This code works fine:-
public boolean isEverywhere(int[] nums, int val) {
for(int i=0;i<=nums.length-2;i++){
if(nums[i]!=val&&nums[i+1]!=val){
return false;
}
}
return true;
}
public class IE {
static boolean isEverywhere(int[] a, int val) {
for (int i = 0; i < a.length; i++) {
System.out.println("*** iteration: " + i);
System.out.println("a[" + (i-1) + "]=" + (i > 0 ? a[i-1] : "n/a"));
System.out.println("a[" + i + "]=" + a[i]);
System.out.println("a[" + (i+1) + "]=" + (i < a.length -1 ? a[i+1] : "n/a"));
if (a[i] != val && (i > 0 ? a[i-1] != val : true) && (i < a.length-1 ? a[i+1] != val : true)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
int[] a = new int[] {1, 2, 1, 3};
System.out.println(isEverywhere(a, 1));
a = new int[] {1, 2, 1, 3};
System.out.println(isEverywhere(a, 2));
a = new int[] {1, 2, 1, 3, 4};
System.out.println(isEverywhere(a, 1));
}
}
Basically, for a given element in the array, the test fails if the value isn't adjacent, either before or after it.

Categories

Resources