Can't change variable while doing recursion - java

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.

Related

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);
}

Merge Sort Recursion

This is a code from Introduction to Java Programming about Merge Sort. This method uses a recursion implementation.
public class MergeSort {
2 /** The method for sorting the numbers */
3 public static void mergeSort(int[] list) {
4 if (list.length > 1) {
5 // Merge sort the first half
6 int[] firstHalf = new int[list.length / 2];
7 System.arraycopy(list, 0, firstHalf, 0, list.length / 2);
8 mergeSort(firstHalf);
9
10 // Merge sort the second half
11 int secondHalfLength = list.length - list.length / 2;
12 int[] secondHalf = new int[secondHalfLength];
13 System.arraycopy(list, list.length / 2,
14 secondHalf, 0, secondHalfLength);
15 mergeSort(secondHalf);
16
17 // Merge firstHalf with secondHalf into list
18 merge(firstHalf, secondHalf, list);
19 }
20 }
My question: is in Line 8 calls the recursion method back to "mergeSort"? If running from the beginning of the method, the "firstHalf" array will be created again and the length will be half short. I think the "firstHalf" can not created again and the length should not be changed if an array is defined already.
Here is the whole code link: Merge Sort Java.
This is beginner's way of thinking. Yes, exactly I thought the same when I encountered this before. I couldn't believe that the same array size can change dynamically. Understand this, in the below code, array l and array r are created with different sizes for every recursive call. Don't confuse on this.
Yes, this is never possible that the same array size changes dynamically for a beginner like you and me. But, there is an exception, well, there are exceptions. We will see them very often as we move forward.
Its recursion, in recursion things change dynamically and all this
changes are stored in a call stack.
Its confusing but its really interesting if you ponder over it. Its profound. Merge sort can be implemented in quite different ways, but the underlying concept of recursion is same. Don't get confused here, Its better you follow another way to do it, video:
Merge sort first takes a list or an array. Lets imagine the
a.length; #lenght of an array is 8
Now the end goal is to split the array recursively, till it reaches to a point where there are no-elements (only-one). And a single element is always sorted.
See the base case in the below code:
if(a.length<2) /*Remember this is the base case*/
{
return;
}
Once it reaches to single element, sort and merge them back. This way you get a complete sorted array which is easy to merge. The only reason we are doing all this non-sense is to get a better run-time algorithm which is O(nlogn).
Because, all the other sorting algos (insertion, bubble, and selection) will take O(n2), which is alot, too much indeed. So, humanity must figure out the better solution. Its a need for humanity, very important. I know its annoying, I had gone through this non-sense.
Please do some research on recursion before you attempt on this. Understand recursion clearly. Keep all this away. Take a simple recursion example and start working on it. Take a factorial example. Its a bad example but its easy to understand.
Top-down MergeSort
See my code, its nice and easy. Again, both are not easy to understand on your first attempt. You must get in touch with recursion before you attempt to understand these things. All the very best.
public class MergeSort
{
private int low;
private int high;
private int mid;
public static int[] a;
public MergeSort(int x)
{
a = new int[x];
a[0]=19;
a[1]=10;
a[2]=0;
a[3]=220;
a[4]=80;
a[5]=2000;
a[6]=56001;
a[7]=2;
}
public void division(int[] a)
{
low=0;
int p;
high = a.length;
mid = (high+low)/2;
if(a.length<2) /*Remember this is the base case*/
{
return;
}
else
{
int[] l = new int[mid];
int[] r = new int[high-mid];
/*copying elements from a into l and r*/
for(p=0;p<mid;p++)
l[p]=a[p];
for(int q=0;q<high-mid;q++, p++)
r[q]=a[p];
/*first recursive call starts from here*/
division(l);
division(r);
sortMerge(a, l, r);
}
}
public void sortMerge(int[] a, int[] l, int[] r)
{
int i=0, j=0, k=0;
/*sorting and then merging recursively*/
while(i<l.length && j<r.length)
{
if(l[i]<r[j])
{
a[k] = l[i]; /*copying sorted elements into a*/
i++;
k++;
}
else
{
a[k] = r[j];
j++;
k++;
}
}
/*copying remaining elements into a*/
while(i<l.length)
{
a[k] = l[i];
i++;
k++;
}
while(j<r.length)
{
a[k] = r[j];
j++;
k++;
}
}
/*method display elements in an array*/
public void display()
{
for(int newIndex=0;newIndex<a.length;newIndex++)
{
System.out.println(a[newIndex]);
}
}
public static void main(String[] args)
{
MergeSort obj = new MergeSort(8);
obj.division(a);
obj.display();
}
}
As it was pointed out by Emz: This is due to scope reasons. A local variable is a new object.
[
Local variables are declared by local variable declaration statements
(§14.4).
Whenever the flow of control enters a block (§14.2) or for statement
(§14.14), a new variable is created for each local variable declared
in a local variable declaration statement immediately contained within
that block or for statement.
A local variable declaration statement may contain an expression which
initializes the variable. The local variable with an initializing
expression is not initialized, however, until the local variable
declaration statement that declares it is executed. (The rules of
definite assignment (§16) prevent the value of a local variable from
being used before it has been initialized or otherwise assigned a
value.) The local variable effectively ceases to exist when the
execution of the block or for statement is complete.]1
Here is an alternative implementation of merge sort, this is bottom-up MergeSort
public class MergeSort {
public static void merge(int[]a,int[] aux, int f, int m, int l) {
for (int k = f; k <= l; k++) {
aux[k] = a[k];
}
int i = f, j = m+1;
for (int k = f; k <= l; k++) {
if(i>m) a[k]=aux[j++];
else if (j>l) a[k]=aux[i++];
else if(aux[j] > aux[i]) a[k]=aux[j++];
else a[k]=aux[i++];
}
}
public static void sort(int[]a,int[] aux, int f, int l) {
if (l<=f) return;
int m = f + (l-f)/2;
sort(a, aux, f, m);
sort(a, aux, m+1, l);
merge(a, aux, f, m, l);
}
public static int[] sort(int[]a) {
int[] aux = new int[a.length];
sort(a, aux, 0, a.length-1);
return a;
}
}
To understand how Merge Sort works you must understand two core data structures, Arrays and Stacks. Stacks are LIFO (Last in First Out). Method calls are executed using Stacks, so the last method call is executed first. Due to these factors, the Merge Sort has this unique behavior.
For example let's take an array as an input:
int[] input = new array[] {12, 11, 13, 5, 6, 7};
Now let's implement a Merge Sort on this array:
'''
class MergeSort
{
private static void merge_sort(int[] arr)
{
if (arr.length > 1)
{
int midpoint = arr.length / 2;
int[] l_arr = new int[midpoint];
int[] r_arr = new int[arr.length - midpoint];
int L_index = 0;
int R_index = 0;
// SORTING [ BEGIN ]
// [ BEGIN ]
// WHILE LOOP THAT IS FILLING THE LEFT ARRAY
//
while(L_index < l_arr.length )
{
l_arr[L_index] = arr[L_index];
if (L_index + 1 < l_arr.length)
{
l_arr[L_index + 1] = arr[L_index + 1];
L_index++;
}
L_index++;
}
// [ END ]
L_index = midpoint;
// [ BEGIN ]
// A WHILE LOOP THAT IS FILLING THE RIGHT ARRAY
//
while(R_index < r_arr.length)
{
r_arr[R_index] = arr[L_index];
if (R_index + 1 < r_arr.length)
{
r_arr[R_index + 1] = arr[L_index + 1];
L_index++;
R_index++;
}
L_index++;
R_index++;
}
// [ END ]
merge_sort(l_arr);
merge_sort(r_arr);
// SORTING [ END ]
// MEGING [ BEGIN ]
int l_index = 0;
int r_index = 0;
int index = 0;
while (l_index < l_arr.length && r_index < r_arr.length )
{
if (l_arr[l_index] <= r_arr[r_index])
{
arr[index] = l_arr[l_index];
l_index++;
}
else
{
arr[index] = r_arr[r_index];
r_index++;
}
index++;
}
while (l_index < l_arr.length)
{
arr[index] = l_arr[l_index];
l_index++;
index++;
}
while (r_index < r_arr.length)
{
arr[index] = r_arr[r_index];
r_index++;
index++;
}
// MEGING [ END ]
}
}
public static void main(String[] args)
{
int[] arr = new int[] {12, 11, 13, 5, 6, 7};
// BEGIN THE MERGE SORT
merge_sort(arr);
}
}
'''
When the merge sort is called the array is split into two arrays, the left array and right array. When the split happens, the left and right arrays are filled, and then recursion occurs.
The split happens always on the left until no split cannot be done, then the split transitions to the right half.
When the array reaches the size of one, the recursion stops, giving control to the previous method call. When no recursion cannot be performed, the code execution will go bellow the recursive method calls and the merge section of the algorithm will arrange the two halves in increasing / decreasing order and pass the control back to its own caller method instance.
Now the magic happens. When the array is given as a parameter to a method and it is sorted, the modifications done on the array parameter will affect the array that is within the caller method instance because, arrays are passed by reference and not by value. So this means that each time recursion occurs and it is passing the left or right half of the array, it is passing a reference to the left or right array and the modifications done by the called method instance will affect the array passed as a parameter in the caller method.

algorithm removing duplicate elements in array without auxillay storage

I am working on this famous interview question on removing duplicate elements in array without using auxillary storage and preserving the order;
I have read a bunch of posts; Algorithm: efficient way to remove duplicate integers from an array, Removing Duplicates from an Array using C.
They are either implemented in C (without explanation) or the Java Code provided just fails when there is consecutive duplicates such as [1,1,1,3,3].
I am not quite confident with using C, my background is Java. So I implemented the code myself;
it follows like this:
use two loops, the outer-loop traverses the array and inner loop checks for duplicates and if present replace it with null.
Then I go over the duplicate-replaced-null array and remove null elements and replacing it with the next non-null element.
The total run-time I see now is O(n^2)+O(n) ~ O(n^2). Reading the above posts, I understood this is the best we can do, if no sorting and auxiliary storage is allowed.
My code is here: I am looking for ways to optimize any further (if there is a possibility) or a better/simplisitc logic;
public class RemoveDup {
public static void main (String[] args){
Integer[] arr2={3,45,1,2,3,3,3,3,2,1,45,2,10};
Integer[] res= removeDup(arr2);
System.out.println(Arrays.toString(res));
}
private static Integer[] removeDup(Integer[] data) {
int size = data.length;
int count = 1;
for (int i = 0; i < size; i++) {
Integer temp = data[i];
for (int j = i + 1; j < size && temp != null; j++) {
if (data[j] == temp) {
data[j] = null;
}
}
}
for (int i = 1; i < size; i++) {
Integer current = data[i];
if (data[i] != null) {
data[count++] = current;
}
}
return Arrays.copyOf(data, count);
}
}
EDIT 1; Reformatted code from #keshlam throws ArrayIndexOutofBound Exception:
private static int removeDupes(int[] array) {
System.out.println("method called");
if(array.length < 2)
return array.length;
int outsize=1; // first is always kept
for (int consider = 1; consider < array.length; ++consider) {
for(int compare=0;compare<outsize;++compare) {
if(array[consider]!=array[compare])
array[outsize++]=array[consider]; // already present; advance to next compare
else break;
// if we get here, we know it's new so append it to output
//array[outsize++]=array[consider]; // could test first, not worth it.
}
}
System.out.println(Arrays.toString(array));
// length is last written position plus 1
return outsize;
}
OK, here's my answer, which should be O(N*N) worst case. (With smaller constant, since even worstcase I'm testing N against -- on average -- 1/2 N, but this is computer science rather than software engineering and a mere 2X speedup isn't significant. Thanks to #Alexandru for pointing that out.)
1) Split cursor (input and output advanced separately),
2) Each new value only has to be compared to what's already been kept, and compare can stop if a match is found. (The hint keyword was "incremental")
3) First element need not be tested.
4) I'm taking advantage of labelled continue where I could have instead set a flag before breaking and then tested the flag. Comes out to the same thing; this is a bit more elegant.
4.5) I could have tested whether outsize==consider and not copied if that was true. But testing for it would take about as many cycles as doing the possibly-unnecessary copy, and the majority case is that they will not be the same, so it's easier to just let a possibly redundant copy take place.
5) I'm not recopying the data in the key function; I've factored out the copy-for-printing operation to a separate function to make clear that removeDupes does run entirely in the target array plus a few automatic variables on the stack. And I'm not spending time zeroing out the leftover elements at the end of the array; that may be wasted work (as in this case). Though I don't think it would actually change the formal complexity.
import java.util.Arrays;
public class RemoveDupes {
private static int removeDupes(final int[] array) {
if(array.length < 2)
return array.length;
int outsize=1; // first is always kept
outerloop: for (int consider = 1; consider < array.length; ++consider) {
for(int compare=0;compare<outsize;++compare)
if(array[consider]==array[compare])
continue outerloop; // already present; advance to next compare
// if we get here, we know it's new so append it to output
array[outsize++]=array[consider]; // could test first, not worth it.
}
return outsize; // length is last written position plus 1
}
private static void printRemoveDupes(int[] array) {
int newlength=removeDupes(array);
System.out.println(Arrays.toString(Arrays.copyOfRange(array, 0, newlength)));
}
public static void main(final String[] args) {
printRemoveDupes(new int[] { 3, 45, 1, 2, 3, 3, 3, 3, 2, 1, 45, 2, 10 });
printRemoveDupes(new int[] { 2, 2, 3, 3 });
printRemoveDupes(new int[] { 1, 1, 1, 1, 1, 1, 1, 1 });
}
}
LATE ADDITION: Since folks expressed confusion about point 4 in my explanation, here's the loop rewritten without labelled continue:
for (int consider = 1; consider < array.length; ++consider) {
boolean matchfound=false;
for(int compare=0;compare<outsize;++compare) {
if(array[consider]==array[compare]) {
matchfound=true;
break;
}
if(!matchFound) // only add it to the output if not found
array[outsize++]=array[consider];
}
Hope that helps. Labelled continue is a rarely-used feature of Java, so it isn't too surprising that some folks haven't seen it before. It's useful, but it does make code harder to read; I probably wouldn't use it in anything much more complicated than this simple algorithm.
Here one version which doesn't use additional memory (except for the array it returns) and doesn't sort either.
I believe this is slightly worse than O(n*log n).
Edit: I'm wrong. This is slightly better than O(n^3).
public class Dupes {
private static int[] removeDupes(final int[] array) {
int end = array.length - 1;
for (int i = 0; i <= end; i++) {
for (int j = i + 1; j <= end; j++) {
if (array[i] == array[j]) {
for (int k = j; k < end; k++) {
array[k] = array[k + 1];
}
end--;
j--;
}
}
}
return Arrays.copyOf(array, end + 1);
}
public static void main(final String[] args) {
System.out.println(Arrays.toString(removeDupes(new int[] { 3, 45, 1, 2, 3, 3, 3, 3, 2, 1, 45, 2, 10 })));
System.out.println(Arrays.toString(removeDupes(new int[] { 2, 2, 3, 3 })));
System.out.println(Arrays.toString(removeDupes(new int[] { 1, 1, 1, 1, 1, 1, 1, 1 })));
}
}
and here's a modified version which doesn't shift all of the elements from after the dupe. Instead it simply switches the dupe with the last, non-matching element. This obviously can't guarantee order.
private static int[] removeDupes(final int[] array) {
int end = array.length - 1;
for (int i = 0; i <= end; i++) {
for (int j = i + 1; j <= end; j++) {
if (array[i] == array[j]) {
while (end >= j && array[j] == array[end]) {
end--;
}
if (end > j) {
array[j] = array[end];
end--;
}
}
}
}
return Arrays.copyOf(array, end + 1);
}
Here you have a worst case of O(n^2) where the return points to the first non unique element. So everything before it is unique.
Instead of C++ iterators indices in Java can be used.
std::vecotr<int>::iterator unique(std::vector<int>& aVector){
auto end = aVector.end();
auto start = aVector.begin();
while(start != end){
auto num = *start; // the element to check against
auto temp = ++start; // start get incremented here
while (temp != end){
if (*temp == num){
std::swap(temp,end);
end--;
}
else
temp++; // the temp is in else so that if the swap occurs the algo should still check the swapped element.
}
}
return end;
}
Java equivalent code: (the return will be an int which is the index of the first not unique element)
int unique(int[] anArray){
int end = anArray.length-1;
int start = 0;
while(start != end){
int num = anArry[start]; // the element to check against
int temp = ++start; // start get incremented here
while (temp != end){
if (anArry[temp] == num){
swap(temp,end); // swaps the values at index of temp and end
end--;
}
else
temp++; // the temp is in else so that if the swap occurs the algo should still check the swapped element.
}
}
return end;
}
The slight difference in this algo and yours is in your point 2. Where instead of replacing the current element with null you go with swapping it with the last possibly unique element which on the first swap is the last element of array, on second swap the second last and so on.
You might as well consider looking at the std::unique implementation in C++ which is linear in one less than the distance between first and last: Compares each pair of elements, and possibly performs assignments on some of them., but as it was noted by #keshlam it is used on sorted arrays only. The return value is the same as in my algo. Here is the code directly from the standard library:
template<class _FwdIt, class _Pr> inline
_FwdIt _Unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
{ // remove each satisfying _Pred with previous
if (_First != _Last)
for (_FwdIt _Firstb; (_Firstb = _First), ++_First != _Last; )
if (_Pred(*_Firstb, *_First))
{ // copy down
for (; ++_First != _Last; )
if (!_Pred(*_Firstb, *_First))
*++_Firstb = _Move(*_First);
return (++_Firstb);
}
return (_Last);
}
To bring in a bit perspective - one solution in Haskell, it uses lists instead of arrays
and returns the reversed order, which can be fixed by applying reverse at the end.
import Data.List (foldl')
removeDup :: (Eq a) => [a] -> [a]
removeDup = foldl' (\acc x-> if x `elem` acc then acc else x:acc) []

How to reverse an array of strings recursively?

supposed to reverse an array of strings recursively.
having trouble implementing this. if i was using a for loop i would just start it at the end of the array and print out the array starting with the last element and ending with the first.
I'm not too sure how to do it recursively. i was thinking about using a swap but that idea sort of fizzled when i couldnt figure out how to change the elements that i was swapping.
any ideas or a push in the right direction would be appreciated.
this is what icame up with so far. i know its wrong, i get an error out of bounds exception which im not sure how to fix. I think im not swapping the first and last correctly. but am i getting the right idea?
this is what i came up with.
a is an array. its inside a class.
// reverse an array
public void rev()
{
rev(0,a.length-1);
}
private void rev(int first, int last)
{
if(last == 0)
{
//do nothing
}
else
{
while(first != last)
{
int temp = first;
first = last;
last = temp;
System.out.print(" " + a[first]);
rev((first + 1), (last - 1));
}
}
}
made some changes and it reverses the last 3 elements but the it repeats the second element. i have no if statement that controls when it runs so shouldnt it run until left = right?
this is what i changed it to
// reverse an array
public void rev()
{
rev(0,a.length-1);
}
private void rev(int first, int last)
{
if(last == 0)
{
//do nothing
}
else
{
String temp = a[first];
a[first] = a[last];
a[last] = temp;
System.out.print(" " + a[first]);
rev(first+ 1, last-1);
}
}
The trick with recursion is to try and think of the problem in terms of a base case and then a way to reduce everything to that base case.
So, if you're trying to reverse a list then you can think of it like this:
The reverse of a list of size 1 is that list.
For a list of size > 1 then the first element in the output list will be the last element of the input list.
The rest of the output list will be the reverse of the input list, minus the last element.
You now have your recursive definition.
Hope that helps.
the while loop is too much, since you are using recursion anyway, try it like this
private void rev(int first, int last)
{
if(first < last)
{
var temp = a[first];
a[first] = a[last];
a[last] = temp;
rev(first + 1, last - 1);
}
}
I always like having a simple public method that calls the private recursive one. That way from other places in your code you just give it the array, and don't have to worry about the other arguments. Also, this catches empty arrays, but you would still need to check for null at some point near the start. Maybe throw an exception in the public method if the array is null?
public String[] reverseArray(String[] theArray) {
this.reverseArrayWorker(theArray, 0, theArray.length -1);
}
private String[] reverseArrayWorker(String[] theArray, int left, int right) {
// Check your base cases first
if (theArray.length <= 1) {
// Array is one element or empty
return theArray;
} else if (left - right <= 0) {
// If there are an odd # of items in the list you hit the center
// If there are an even number your indexes past each other
return theArray;
}
// Make the recursive call
this.reverseArrayWorker(theArray, left + 1, right - 1);
// Switch the two elements at this level
String temp = theArray[left];
theArray[left] = theArray[right];
theArray[right] = temp;
// Return the array up a level
return theArray;
}
public int[] reverse(int[] returnMe, int[] original, int curPos){
if (original.length == 1){
return original;
}else{
if (curPos < original.length){
returnMe[curPos] = original[original.length - 1 - curPos];
reverse(returnMe, original, curPos + 1);
}else{
return returnMe;
}
}
}
Here is an example (but without A String since it is homework) but hopefully it will give you the idea.
public static List<Character> reverse(List<Character> chars) {
return chars.isEmpty() ? chars :
addToList(chars.get(0), reverse(chars.subList(1, chars.length()));
}
public static T List<T> addToList(T t, List<T> ts) {
List<T> ret = new ArrayList<T>();
ret.addAll(ts);
ret.add(t);
return ret;
}
This will work too. Kinda Lisp-like solution.
public static List<String> append(String x, List<String> xs) {
xs.add(x);
return xs;
}
public static List<String> reverse(List<String> xs) {
return xs.isEmpty()
? xs
: append(xs.get(0), reverse(xs.subList(1, xs.size())));
}
I/O:
List ==> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Reversed list ==> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

How do you remove the first instance of an element value in an array?

Add a method void removeFirst(int newVal) to the IntegerList class that removes the first occurrence of a value from the list. If the value does not appear in the list, it should do nothing (but it's not an error). Removing an item should not change the size of the array, but note that the array values do need to remain contiguous, so when you remove a value you will have to shift everything after it down to fill up its space. Also remember to decrement the variable that keeps track of the number of elements.
Please help, I have tried all of the other solutions listed on this site regarding "removing an element from an array" and none have worked.
This method supports the same functionality as Collection.remove() which is how an ArrayList removes the first matching element.
public boolean remove(int n) {
for (int i = 0; i < size; i++) {
if (array[i] != n) continue;
size--;
System.arraycopy(array, i + 1, array, i, size - i);
return true;
}
return false;
}
Rather than write this code yourself, I suggest you look at Trove4J's TIntArrayList which is a wrapper for int[] You can also read the code for ArrayList to see how it is written.
You could do this:
int count; //No of elements in the array
for(i=0;i<count;i++)
{
if(Array[i]==element )
{
swap(Array,i,count);
if(count)
--count;
break;
}
}
int swap(int Array[],int i,int count)
{
int j;
for(j=i;j<=count-i;j++)
a[i]=a[i+1];
}
This is not the Full Implementation.You have to create a class and do this.
Using the method below
public static <TypeOfObject> TypeOfObject[] removeFirst(TypeOfObject[] array, TypeOfObject valueToRemove) {
TypeOfObject[] result = Arrays.copyOf(array, array.length - 1);
List<TypeOfObject> tempList = new ArrayList<>();
tempList.addAll(Arrays.asList(array));
tempList.remove(valueToRemove);
return tempList.toArray(result);
}
You can remove the first element of any array by calling the method as demonstrated in the below JUnit test.
#Test
public void removeFirstTest() {
// Given
Integer valToRemove = 5;
Integer[] input = {1,2,3,valToRemove,4,valToRemove,6,7,8,9};
Integer[] expected = {1,2,3,4,valToRemove,6,7,8,9};
// When
Integer[] actual = removeFirst(input, valToRemove);
// Then
Assert.assertArrayEquals(expected, actual);
}

Categories

Resources