Filter odd numbers recursively - java

How would you solve the following task:
Write a recursive method which gets passed an array, filters all odd numbers and store them into an array. The returned array has to be sorted by each elements order.
You are not allowed to use any provided methods by java classes like Arrays.sort, Lists, etc. Furthermore loops are disallowed and generic well known sort algorithm applied to the result as well.
The part of filtering is easy, but I don't know how to put each element at its right place. At the moment my method only returns an unsorted array with all odd numbers.
public static int[] filterOdd(int[] m){
return filterOdd(m, 0, 0);
}
private static int[] filterOdd(int[] m, int idx, int idxToPlace){
if(idx <= m.length -1){
if(m[idx] % 2 == 0){
return filterOdd(m, idx + 1, idxToPlace);
}else{
int[] buffer = filterOdd(m, idx + 1, idxToPlace + 1);
buffer[idxToPlace] = m[idx];
return buffer;
}
}else{
return new int[numberOfOddIntegers(m)];
}
}
Is there any way to insert the odd number at its right place recursively?

At the place where you do buffer[idxToPlace] = m[idx]; you have to call another method that will return the sorted array with the current processing number added to it.
That new method can be recursive too: you know at that moment that the array you have in your hands is ordered. You just recursively traverse (for example from the end to the begin) and from the moment your element fits in (e.g. is smaller than the previous element) you can insert it and return the sorted array. If there is only 1 element (base case) you can just return it.
That way, at the end of your algorithm, the list will be sorted.

I'm not allowed to use System.arraycopy
This means that you need to figure out how many odd numbers you are going to have, in order to size your result properly:
public static int[] filterOdd(int[] m){
int[] res = new int[countOdd(m, 0)];
filterOdd(m, 0, 0, res);
return res;
}
private static int countOdd(int[] m, int i) {
if (i == m.length) {
return 0;
}
int isOdd = m[i] % 2 != 0 ? 1 : 0;
return isOdd + countOdd(m, i+1);
}
private static void filterOdd(int[] m, int src, int dest, int[] res){
if(src == m.length) {
return;
}
if (m[src] % 2 != 0) {
res[dest++] = m[src];
}
filterOdd(m, src+1, dest, res);
}

Related

Recursively finding the average of even numbers in an array

I'm trying to find the average of all even numbers in an array using recursion and I'm stuck.
I realize that n will have to be decremented for each odd number so I divide by the correct value, but I can't wrap my mind around how to do so with recursion.
I don't understand how to keep track of n as I go, considering it will just revert when I return.
Is there a way I'm missing to keep track of n, or am I looking at this the wrong way entirely?
EDIT: I should have specified, I need to use recursion specifically. It's an assignment.
public static int getEvenAverage(int[] A, int i, int n)
{
// first element
if (i == 0)
if (A[i] % 2 == 0)
return A[0];
else
return 0;
// last element
if (i == n - 1)
{
if (A[i] % 2 == 0)
return (A[i] + getEvenAverage(A, i - 1, n)) / n;
else
return (0 + getEvenAverage(A, i - 1, n)) / n;
}
if (A[i] % 2 == 0)
return A[i] + getEvenAverage(A, i - 1, n);
else
return 0 + getEvenAverage(A, i - 1, n);
}
In order to keep track of the number of even numbers you have encountered so far, just pass an extra parameter.
Moreover, you can also pass an extra parameter for the sum of even numbers and when you hit the base case you can return the average, that is, sum of even numbers divided by their count.
One more thing, your code has two base cases for the first as well as last element which is unneeded.
You can either go decrementing n ( start from size of array and go till the first element ), or
You can go incrementing i starting from 0 till you reach size of array, that is, n.
Here, is something I tried.
public static int getEvenAvg(int[] a, int n, int ct, int sum) {
if (n == -1) {
//make sure you handle the case
//when count of even numbers is zero
//otherwise you'll get Runtime Error.
return sum/ct;
}
if (a[n]%2 == 0) {
ct++;
sum+=a[n];
}
return getEvenAvg(a, n - 1, ct, sum);
}
You can call the function like this getEvenAvg(a, size_of_array - 1, 0, 0);
Example
When dealing with recursive operations, it's often useful to start with the terminating conditions. So what are our terminating conditions here?
There are no more elements to process:
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
... okay, now how do we reduce the number of elements to process? We should probably increment index?
index++;
... oh, but only when going to the next level:
getEvenAverage(elements, index++, sum, count);
Well, we're also going to have to add to sum and count, right?
sum += a[index];
count++;
.... except, only if the element is even:
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
... and that's about it:
static int getEvenAverage(int[] elements, int index, int sum, int count) {
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
return getEvenAverage(elements, index + 1, sum, count);
}
... although you likely want a wrapper function to make calling it prettier:
static int getEvenAverage(int[] elements) {
return getEvenAverage(elements, 0, 0, 0);
}
Java is not a good language for this kind of thing but here we go:
public class EvenAverageCalculation {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7,8,9,10};
System.out.println(getEvenAverage(array));
}
public static double getEvenAverage(int[] values) {
return getEvenAverage(values, 0, 0);
}
private static double getEvenAverage(int[] values, double currentAverage, int nrEvenValues) {
if (values.length == 0) {
return currentAverage;
}
int head = values[0];
int[] tail = new int[values.length - 1];
System.arraycopy(values, 1, tail, 0, tail.length);
if (head % 2 != 0) {
return getEvenAverage(tail, currentAverage, nrEvenValues);
}
double newAverage = currentAverage * nrEvenValues + head;
nrEvenValues++;
newAverage = newAverage / nrEvenValues;
return getEvenAverage(tail, newAverage, nrEvenValues);
}
}
You pass the current average and the number of even elements so far to each the recursive call. The new average is calculated by multiplying the average again with the number of elements so far, add the new single value and divide it by the new number of elements before passing it to the next recursive call.
The way of recreating new arrays for each recursive call is the part that is not that good with Java. There are other languages that have syntax for splitting head and tail of an array which comes with a much smaller memory footprint as well (each recursive call leads to the creation of a new int-array with n-1 elements). But the way I implemented that is the classical way of functional programming (at least how I learned it in 1994 when I had similar assignments with the programming language Gofer ;-)
Explanation
The difficulties here are that you need to memorize two values:
the amount of even numbers and
the total value accumulated by the even numbers.
And you need to return a final value for an average.
This means that you need to memorize three values at once while only being able to return one element.
Outline
For a clean design you need some kind of container that holds those intermediate results, for example a class like this:
public class Results {
public int totalValueOfEvens;
public int amountOfEvens;
public double getAverage() {
return totalValueOfEvens + 0.0 / amountOfEvens;
}
}
Of course you could also use something like an int[] with two entries.
After that the recursion is very simple. You just need to recursively traverse the array, like:
public void method(int[] values, int index) {
// Abort if last element
if (index == values.length - 1) {
return;
}
method(array, index + 1);
}
And while doing so, update the container with the current values.
Collecting backwards
When collecting backwards you need to store all information in the return value.
As you have multiple things to remember, you should use a container as return type (Results or a 2-entry int[]). Then simply traverse to the end, collect and return.
Here is how it could look like:
public static Results getEvenAverage(int[] values, int curIndex) {
// Traverse to the end
if (curIndex != values.length - 1) {
results = getEvenAverage(values, curIndex + 1);
}
// Update container
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
// Return accumulated results
return results;
}
Collecting forwards
The advantage of this method is that the caller does not need to call results.getAverage() by himself. You store the information in the parameters and thus be able to freely choose the return type.
We get our current value and update the container. Then we call the next element and pass him the current container.
After the last element was called, the information saved in the container is final. We now simply need to end the recursion and return to the first element. When again visiting the first element, it will compute the final output based on the information in the container and return.
public static double getEvenAverage(int[] values, int curIndex, Results results) {
// First element in recursion
if (curIndex == 0) {
// Setup the result container
results = new Results();
}
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
int returnValue = 0;
// Not the last element in recursion
if (curIndex != values.length - 1) {
getEvenAverage(values, curIndex + 1, results);
}
// Return current intermediate average,
// which is the correct result if current element
// is the first of the recursion
return results.getAverage();
}
Usage by end-user
The backward method is used like:
Results results = getEvenAverage(values, 0);
double average results.getAverage();
Whereas the forward method is used like:
double average = getEvenAverage(values, 0, null);
Of course you can hide that from the user using a helper method:
public double computeEvenAverageBackward(int[] values) {
return getEvenAverage(values, 0).getAverage();
}
public double computeEvenAverageForward(int[] values) {
return getEvenAverage(values, 0, null);
}
Then, for the end-user, it is just this call:
double average = computeEvenAverageBackward(values);
Here's another variant, which uses a (moderately) well known recurrence relationship for averages:
avg0 = 0
avgn = avgn-1 + (xn - avgn-1) / n
where avgn refers to the average of n observations, and xn is the nth observation.
This leads to:
/*
* a is the array of values to process
* i is the current index under consideration
* n is a counter which is incremented only if the current value gets used
* avg is the running average
*/
private static double getEvenAverage(int[] a, int i, int n, double avg) {
if (i >= a.length) {
return avg;
}
if (a[i] % 2 == 0) { // only do updates for even values
avg += (a[i] - avg) / n; // calculate delta and update the average
n += 1;
}
return getEvenAverage(a, i + 1, n, avg);
}
which can be invoked using the following front-end method to protect users from needing to know about the parameter initialization:
public static double getEvenAverage(int[] a) {
return getEvenAverage(a, 0, 1, 0.0);
}
And now for a completely different approach.
This one draws on the fact that if you have two averages, avg1 based on n1 observations and avg2 based on n2 observations, you can combine them to produce a pooled average:
avgpooled = (n1 * avg1 + n2 * avg2) / (n1 + n2).
The only issue here is that the recursive function should return two values, the average and the number of observations on which that average is based. In many other languages, that's not a problem. In Java, it requires some hackery in the form of a trivial, albeit slightly annoying, helper class:
// private helper class because Java doesn't allow multiple returns
private static class Pair {
public double avg;
public int n;
public Pair(double avg, int n) {
super();
this.avg = avg;
this.n = n;
}
}
Applying a divide and conquer strategy yields the following recursion:
private static Pair getEvenAverage(int[] a, int first, int last) {
if (first == last) {
if (a[first] % 2 == 0) {
return new Pair(a[first], 1);
}
} else {
int mid = (first + last) / 2;
Pair p1 = getEvenAverage(a, first, mid);
Pair p2 = getEvenAverage(a, mid + 1, last);
int total = p1.n + p2.n;
if (total > 0) {
return new Pair((p1.n * p1.avg + p2.n * p2.avg) / total, total);
}
}
return new Pair(0.0, 0);
}
We can deal with empty arrays, protect the end-user from having to know about the book-keeping arguments, and return just the average by using the following public front-end:
public static double getEvenAverage(int[] a) {
return a.length > 0 ? getEvenAverage(a, 0, a.length - 1).avg : 0.0;
}
This solution has the benefit of O(log n) stack growth for an array of n items, versus O(n) for the various other solutions that have been proposed. As a result, it can deal with much larger arrays without fear of a stack overflow.

Finding the largest element in an array using recursion in Java

This is what I have so far, but I'm confused on how to keep track of the index. I would change the parameters of the method, but I'm not allowed.
I can only use a loop to make another array. Those are the restrictions.
public class RecursiveFinder {
static int checkedIndex = 0;
static int largest = 0;
public static int largestElement(int[] start){
int length = start.length;
if(start[length-1] > largest){
largest = start[length-1];
int[] newArray = Arrays.copyOf(start, length-1);
largestElement(newArray);
}
else{
return largest;
}
}
/**
* #param args
*/
public static void main(String[] args) {
int[] array1 = {0,3,3643,25,252,25232,3534,25,25235,2523,2426548,765836,7475,35,547,636,367,364,355,2,5,5,5,535};
System.out.println(largestElement(array1));
int[] array2 = {1,2,3,4,5,6,7,8,9};
System.out.println(largestElement(array2));
}
}
Recursive method doesn't need to keep the largest value inside.
2 parameters method
Start to call with:
largestElement(array, array.length-1)
Here is the method:
public static int largestElement(int[] start, int index) {
if (index>0) {
return Math.max(start[index], largestElement(start, index-1))
} else {
return start[0];
}
}
The 3rd line of method is the hardest one to understand. It returns one of two elements, larges of the one of current index and of remaining elements to be checked recursively.
The condition if (index>0) is similar to while-loop. The function is called as long as the index remains positive (reaches elements in the array).
1 parameter method
This one is a bit tricky, because you have to pass the smaller array than in the previous iteration.
public static int largestElement(int[] start) {
if (start.length == 1) {
return start[0];
}
int max = largestElement(Arrays.copyOfRange(start, 1, start.length));
return start[0] > max ? start[0] : max;
}
I hope you do this for the study purposes, actually noone has a need do this in Java.
Try that for the upper class, leave the main method it's is correct.
public class dammm {
public static int largestElement(int[] start){
int largest = start[0];
for(int i = 0; i<start.length; i++) {
if(start[i] > largest){
largest = start[i];
}
}return largest;
}
If your goal is to achieve this by using recursion, this is the code that you need. It is not the most efficient and it is not the best way to deal with the problem but it is probably what you need.
public static int largestElement(int[] start){
int length = start.length;
if (start.lenght == 1){
return start[0];
} else {
int x = largestElement(Arrays.copyOf(start, length-1))
if (x > start[length-1]){
return x;
} else {
return start[length-1];
}
}
}
Imagine that you have a set of numbers you just have to compare one number with the rest of them.
For example, given the set {1,8,5} we just have to check if 5 is larger than the largest of {1,8}. In the same way you have to check if 8 is larger than the largest of {1}. In the next iteration, when the set one have one value, you know that that value is the bigger of the set.
So, you go back to the previous level and check if the returned value (1) is larger than 8. The result (8) is returned to the previous level and is checked against 5. The conclusion is that 8 is the larger value
One parameter, no copying. Tricky thing is, we need to pass a smaller array to the same method. So a global variable is required.
// Number of elements checked so far.
private static int current = -1;
// returns the largest element.
// current should be -1 when user calls this method.
public static int largestElement(int[] array) {
if (array.length > 0) {
boolean resetCurrent = false;
if (current == -1) {
// Initialization
current = 0;
resetCurrent = true;
} else if (current >= array.length - 1) {
// Base case
return array[array.length - 1];
}
try {
int i = current++;
return Math.max(array[i], largestElement(array));
} finally {
if (resetCurrent) {
current = -1;
}
}
}
throw new IllegalArgumentException("Input array is empty.");
}
If you can create another method, everything would be much simpler.
private static int recursiveFindLargest(int [] array, int i) {
if (i > 0) {
return Math.max(array[i], recursiveFindLargest(array, i-1));
} else {
return array[0];
}
}
public static int largestElement(int [] array) {
// For empty array, we cannot return a value to indicate this situation,
//all integer values are possible for non-empty arrays.
if (array.length == 0) throw new IllegalArgumentException();
return recursiveFindLargest(array, array.length - 1);
}
For this problem you really need to think about working with the base case. Take a look at some of the simple cases you would have to deal with:
If the array is length 1, then you return the only value
If the array is length 2, then you return the maximum of the two values
If the array is length 3, then ?
From the above we can get an idea of the structure of the problem:
if array.length == 1 then
return array[0]
else
return the maximum of the values
In the above if we have only one element, it is the maximum value in the list. If we have two values, then we have to find the maximum of those values. From this, we can then use the idea that if we have three values, we can find the maximum of two of them, then compare the maximum with the third value. Expanding this into pseudo code, we can get something like:
if array.length == 1 then
return array[0]
else
new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
return maximum(array[0], largestElement(new array))
To explain the above a little better, think of execution like a chain (example for {1, 2, 3}).
Array: {1, 2, 3}, maximum(array[0] = 1, largestElement(new array = {2, 3}))
Array: {2, 3}, maximum(array[0] = 2, largestElement(new array = {3}))
Array: {3}, array[0] = 3 => length is 1 so return 3
The above then rolls back up the 'tree' structure where we get:
maximum (1, maximum(2, (return 3)))
Once you have the maximum value, you can use the sample principle as above to find the index with a separate method:
indexOf(array, maximum)
if array[0] == maximum then
return 0
else if array.length == 1 then
return -1
else
new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
result = indexOf(new array, maximum)
return (result == -1) ? result : result + 1
For looking into this more, I would read this from the Racket language. In essence it shows the idea of array made purely from pairs and how you can use recursion to do iteration on it.
If you are interested, Racket is a pretty good resource for understanding recursion. You can check out University of Waterloo tutorial on Racket. It can give you a brief introduction to recursion in an easy to understand way, as well as walking you through some examples to understand it better.
You don't need to keep a largest variable outside your method - that's generally not a good practice with recursion which should return all context of the results.
When you think about recursion try to think in terms of a simple base case where the answer is obvious and then, for all other cases how to break it down into a simpler case.
So in pseduo-code your algorithm should be something like:
func largest(int[] array)
if array has 1 element
return that element
else
return the larger of the first element and the result of calling largest(remaining elements)
You could use Math.max for the 'larger' calculation.
It's unfortunate that you can't change the arguments as it would be easier if you could pass the index to start at or use lists and sublists. But your copying method should work fine (assuming efficiency isn't a concern).
An alternative to the algorithm above is to make an empty array the base case. This has the advantage of coping with empty arrays (by return Integer.MIN_VALUE):
int largest(int[] array) {
return array.length == 0
? Integer.MIN_VALUE
: Math.max(array[0], largest(Arrays.copyOfRange(array, 1, array.length)));
}
Here is working example of code with one method param
public int max(int[] list) {
if (list.length == 2) return Math.max(list[0], list[1]);
int max = max(Arrays.copyOfRange(list, 1, list.length));
return list[0] < max ? max : list[0];
}
private static int maxNumber(int[] arr,int n,int max){
if(n<0){
return max;
}
max = Math.max(arr[n],max);
return maxNumber(arr,n-1,max);
}

Randomizing set of duplicate arrays in Java without repeating elements

In my problem I have few arrays with numbers 1 - 3,
[1,2,3], [1,2,3]
I combined the arrays into one full array,
[1,2,3, 1,2,3]
I need to randomize the array each run, so that no element repeats.
For example, this would work
[1, 2, 1, 3, 2, 3]
but this would not.
[1,2,2,3,1,3]
I chose 1,2,3 to simplify it, but my arrays would consist of the numbers 1 - 6. The idea remains the same though. Is there an algorithm or easy method to accomplish this?
This is a heuristic solution for random shuffling not allowing consecutive duplicates. It applies to lists, but it's easy to transfer it to arrays as it does only swapping and no shift operations are required. It seems to work in the majority of cases for lists consisting of millions of elements and various density factors, but always keep in mind that heuristic algorithms may never find a solution. It uses logic from genetic algorithms, with the exception that this version utilizes one individual and selective mutation only (it's easy to convert it to a real genetic algorithm though), but it's simple and works as follows:
If a duplicate is found, try swapping it with a random element after it; if not possible, try swapping it with an element prior to it (or vice versa). The key point here is the random position for exchanging elements, so as to keep a better uniform distribution on random output.
This question has been asked in alternative forms, but I couldn't find an acceptable solution yet. Unfortunately, as most of the proposed answers (except for the "greedy" extensive re-shuffling till we get a match or computing every combination), this solution does not provide a perfect uniform distribution, but seems to minimize some patterns, :( still not possible to remove every pattern, as you see below. Try it and post any comments for potential improvements.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
//Heuristic Non-Consecutive Duplicate (NCD) Shuffler
public class NCDShuffler {
private static Random random = new Random();
//private static int swaps = 0;
public static <T> void shuffle (List<T> list) {
if (list == null || list.size() <= 1) return;
int MAX_RETRIES = 10; //it's heuristic
boolean found;
int retries = 1;
do {
Collections.shuffle(list);
found = true;
for (int i = 0; i < list.size() - 1; i++) {
T cur = list.get(i);
T next = list.get(i + 1);
if (cur.equals(next)) {
//choose between front and back with some probability based on the size of sublists
int r = random.nextInt(list.size());
if ( i < r) {
if (!swapFront(i + 1, next, list, true)) {
found = false;
break;
}
} else {
if (!swapBack(i + 1, next, list, true)) {
found = false;
break;
}
}
}
}
retries++;
} while (retries <= MAX_RETRIES && !found);
}
//try to swap it with an element in a random position after it
private static <T> boolean swapFront(int index, T t, List<T> list, boolean first) {
if (index == list.size() - 1) return first ? swapBack(index, t, list, false) : false;
int n = list.size() - index - 1;
int r = random.nextInt(n) + index + 1;
int counter = 0;
while (counter < n) {
T t2 = list.get(r);
if (!t.equals(t2)) {
Collections.swap(list, index, r);
//swaps++;
return true;
}
r++;
if (r == list.size()) r = index + 1;
counter++;
}
//can't move it front, try back
return first ? swapBack(index, t, list, false) : false;
}
//try to swap it with an element in a random "previous" position
private static <T> boolean swapBack(int index, T t, List<T> list, boolean first) {
if (index <= 1) return first ? swapFront(index, t, list, false) : false;
int n = index - 1;
int r = random.nextInt(n);
int counter = 0;
while (counter < n) {
T t2 = list.get(r);
if (!t.equals(t2) && !hasEqualNeighbours(r, t, list)) {
Collections.swap(list, index, r);
//swaps++;
return true;
}
r++;
if (r == index) r = 0;
counter++;
}
return first ? swapFront(index, t, list, false) : false;
}
//check if an element t can fit in position i
public static <T> boolean hasEqualNeighbours(int i, T t, List<T> list) {
if (list.size() == 1)
return false;
else if (i == 0) {
if (t.equals(list.get(i + 1)))
return true;
return false;
} else {
if (t.equals(list.get(i - 1)) || (t.equals(list.get(i + 1))))
return true;
return false;
}
}
//check if shuffled with no consecutive duplicates
public static <T> boolean isShuffledOK(List<T> list) {
for (int i = 1; i < list.size(); i++) {
if (list.get(i).equals(list.get(i - 1)))
return false;
}
return true;
}
//count consecutive duplicates, the smaller the better; We need ZERO
public static <T> int getFitness(List<T> list) {
int sum = 0;
for (int i = 1; i < list.size(); i++) {
if (list.get(i).equals(list.get(i - 1)))
sum++;
}
return sum;
}
//let's test it
public static void main (String args[]) {
HashMap<Integer, Integer> freq = new HashMap<Integer, Integer>();
//initialise a list
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(1);
list.add(2);
list.add(3);
/*for (int i = 0; i<100000; i++) {
list.add(random.nextInt(10));
}*/
//Try to put each output in the frequency Map
//then check if it's a uniform distribution
Integer hash;
for (int i = 0; i < 10000; i++) {
//shuffle it
shuffle(list);
hash = hash(list);
if (freq.containsKey(hash)) {
freq.put(hash, freq.get(hash) + 1);
} else {
freq.put(hash, 1);
}
}
System.out.println("Unique Outputs: " + freq.size());
System.out.println("EntrySet: " + freq.entrySet());
//System.out.println("Swaps: " + swaps);
//for the last shuffle
System.out.println("Shuffled OK: " + isShuffledOK(list));
System.out.println("Consecutive Duplicates: " + getFitness(list));
}
//test hash
public static int hash (List<Integer> list) {
int h = 0;
for (int i = 0; (i < list.size() && i < 9); i++) {
h += list.get(i) * (int)Math.pow(10, i); //it's reversed, but OK
}
return h;
}
}
This is a sample output; it's easy to understand the issue with the non-uniform distribution.
Unique Outputs: 6
EntrySet: [1312=1867, 3121=1753, 2131=1877, 1321=1365, 1213=1793, 1231=1345]
Shuffled OK: true
Consecutive Duplicates: 0
You could use Collections.shuffle to randomize the list. Do it in a while loop, until the list passes your constraint.
If the arrays are relatively small, it would not be too hard for you just to combine the two arrays, randomize it then check the numbers, and if there are too same numbers just shift one over or just randomize it again.
There's no pre-written algorithm that I know of (which doesn't mean one doesn't exist), but the problem is easy to understand and the implementation is straightforward.
I will offer two suggestions dependent on if you want to build a valid array or if you want to build an array and then check its validity.
1 - Create some collection (Array, ArrayList, etc) that contains all of the possible values that will be included in your final array. Grab one of those values and add it to the array. Store a copy of that value in a variable. Grab another value from the possible values, check that it's not equal to your previous value, and add it to the array if it's valid.
2 - Create an array that contains the number of values you want. Check that item n != item n+1 for all items except the last one. If you fail one of those checks, either generate a new random value for that location or add or subtract some constant from the value at that location. Once you have checked all of the values in this array, you know you have a valid array. Assuming the first and last values can be the same.
The most optimal solution, I can think of, is to count the number of occurrences of each value, logically creating a "pool" for each distinct value.
You then randomly choose a value from any of the pools that are not the value of the previous selection. The random selection is weighted by pool sizes.
If a pool is more than half the size of all remaining values, then you must choose from that pool, in order to prevent repetition at the end.
This way you can produce result fast without any form of retry or backtracking.
Example (using letters as values to clarify difference from counts):
Input: A, B, C, A, B, C
Action Selected Pools(Count)
A(2) B(2) C(2)
Random from all 3 pools A A(1) B(2) C(2)
Random from B+C pools C A(1) B(2) C(1)
Random from A+B pools (1:2 ratio) A A(0) B(2) C(1)
Must choose B (>half) B A(0) B(1) C(1)
Random from A+C, so C C A(0) B(1) C(0)
Must choose B (>half) B A(0) B(0) C(0)
Result: A, C, A, B, C, B

Can't change variable while doing recursion

public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];
rekursiq(a, b, 0, 0, 1);
}
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (index == b.length){
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
Now my question is: Instead of b.length in the recursion bottom I want to place an int check, and make check go +1 on every going there, and do something.
while (check < b.length) go the if statement, else return; but I can't seem to 1) increase the value properly and 2) make this while correctly. I don't know why.
I think my best try was
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (check > b.length) {
return;
} else {
if (index == check) {
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
}
But it did not work, and I hope some one of you can tell me why and how to fix it.
The value of check does increase when the method is called recursively. However, the problem you have is independent of check.
The Problem
Let me start by repeating what abhishrp already briefly mentioned: In this particular case, you want to either use a loop to iterate over all elements in the array, or recursion, but not use a loop inside of your recursive method. The reason is the following: At each step in the recursion, you look at exactly one element: the element at position index.
The Solution
So, how would you recursively copy an array? Let us assume you have a source array (in your code a) and an empty destination array (in your code b). Now, we know how to copy a single element of the array, namely destination[index] = source[index], and we can imagine copying the array as copying the first element, and then copying the subarray starting at the second element. Note that knowing how to copy a single element in an array implies knowing how to copy an array containing only one element.
This leads us to the following recursion, which we will turn to code shortly after:
if the given index dereferences the last element in the array, then copy this last element.
otherwise, copy the element at the current index, and copy the subarray starting at the next index.
Or expressed in Java:
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
Note that you have too many parameters in your code: The parameter check is really just index, as you want to check whether the index is still inside the bounds of the array. I don't really know what you intended to do with the variable start though - seems like somehow you got confused there because of the loop.
Sidenote
Also, a small justification on why the true-branch of the if-statement in the above code does copy the last element instead of returning nothing if the index is out of bounds as in your code. It's perfectly reasonable to do it like you did. The argument "We trivially know how to copy an empty array" just didn't seem as natural as "knowing how to copy a single element implies knowing how to copy an array consisting of a single element". I encourage you however to adjust the code to "copy an empty array" as a base-case, because it removes the duplication, and more importantly, allows you to copy empty arrays (for which the above implementation would fail horribly).
Code
I also tried to give a comparison between the iterative and the recursive approach:
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
int[] copyOfAUsingIteration = copyArrayUsingIteration(a);
int[] copyOfAUsingRecursion = copyArrayUsingRecursion(a);
assert(Arrays.equals(copyOfAUsingIteration, copyOfAUsingRecursion));
assert(copyOfAUsingIteration != a);
assert(copyOfAUsingRecursion != a);
System.out.println(java.util.Arrays.toString(copyOfAUsingIteration));
System.out.println(java.util.Arrays.toString(copyOfAUsingRecursion));
}
static int[] copyArrayUsingIteration(int[] arrayToCopy) {
int[] result = new int[arrayToCopy.length];
for(int index = 0; index < result.length; index++){
result[index] = arrayToCopy[index];
}
return result;
}
static int[] copyArrayUsingRecursion(int[] arrayToCopy){
if (arrayToCopy.length == 0){
return new int[0];
} else {
int[] result = new int[arrayToCopy.length];
copyValuesFromSourceToDestinationStartingAtIndex(arrayToCopy, result, 0);
return result;
}
}
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
To copy one array to another you can use either iteration or recursion. There is no need to do both. By this I mean there is no need for the for loop inside the rekursiq method.

example about array in java

assume that i have an array int [] arr={1,2,4,5,7} and also have number 6
so i need the result to be 01100 that means that 2+4=6 in the array so the result will be 1 if the number in the sum 0 otherwise
also i need number of bits in the result be the same number as array lenght
i need java method that perform this operation
This is very similar to the subset sum problem, i.e., given a set of integers, determine if a non-empty subset equals zero. In your case, you need to determine if a non-empty subset equals a specific integer. The latter part about filling in the bit array is purely cosmetics.
A simple way to solve it -- albeit not very efficient, i.e., O(2^N*N) -- is to cycle between every possible subset of integers in your array (power set), and determine if the sum of this subset equals the number you are given.
Here is a way to do it recursively. As noted by JG, there is no efficient solution for the general problem.
private static int[] solve(int[] arr, int target, int res[], int length, int sum) {
if (length == arr.length)
return (sum == target)? res : null;
res[length] = 0;
int[] r = solve(arr, target, res, length + 1, sum);
if (r != null)
return r;
res[length] = 1;
r = solve(arr, target, res, length + 1, sum + arr[length]);
if (r != null)
return r;
return null;
}
public static int[] solve(int[] arr, int target) {
return solve(arr, target, new int[arr.length], 0, 0);
}

Categories

Resources