Swapping references in an Array [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Ok, I was misunderstanding the problem. After reading it a couple of times I figured out randInt is actually the method itself i am using to populate the array. So when it says to call randInt its some sort of recursive call I think. This is somehow what it should look like:
static int[] randInt(int i, int j) {
int[] temp = new int[(j - i) + 1];
for ( i = 0; i < j; i++) {
temp[i] = i + 1; // here i populate the array
}
System.out.println(Arrays.toString(temp)); // this prints [1, 2, 3, 4, 5]
for ( i = 1; i < j;i++){
swapReferences(temp[i], temp[randInt(0,i)] ); //this is some sort of recursive call that swaps the references
// btw that statement does not compile, how can i pass a method as a parameter?
}
return temp;
}
static void swapReferences(int a, int b) { //these parameters are wrong, need to be changed
//Method to swap references
}
Sorry for the confusion, but I think thats how it should be correctly.

Java is pass-by-value, so reassigning the parameters as you try to do will not work.
What you need to do is to have the array itself and two integer indices as parameters:
int randInt = generate.nextInt(j-i) + 1; //this is gonna generate a # within the range of the array (so if array is size 5, generates something 1-5)
for ( i = 1; i < j;i++){
swapReferences(temp, i, randInt); //and this is my attempt at swapping the references
randInt = generate.nextInt(i) + 1 ;
}
static void swapReferences(int[] array, int a, int b){
int x = array[a];
array[a] = array[b];
array[b] = x;
}
You can mutate parameters such as arrays passed into a method, as is being done here, but you can't reassign the parameters themselves.

You are just changing the ints that a and b are pointing to, but not what the indicies the array is pointing to. You need to change your swapReferences method to take the array as input, and something like the indicies to swap
static void swapReferences(int[] arr, int indexA, int index B){
int x = arr[indexA];
a = arr[indexB];
b = x;
arr[indexA] = a;
arr[indexB] = b;
}
or
static void swapReferences(int[] arr, int indexA, int indexB){
int x = arr[indexA];
arr[indexA] = arr[indexB];
arr[indexB] = x;
}

Related

Pick from both sides?

The problem statement is :
Given an integer array A of size N.
You can pick B elements from either left or right end of the array A to get maximum sum.
Find and return this maximum possible sum.
NOTE: Suppose B = 4 and array A contains 10 elements then:
You can pick first four elements or can pick last four elements or can pick 1 from front and 3 from back etc . you need to return the maximum possible sum of elements you can pick.
public class Solution {
ArrayList<Integer> c = new ArrayList<>();
ArrayList<Integer> A= new ArrayList<>();
public int solve(ArrayList<Integer> A, int B) {
if (B>A.size()){
int sum=0;
for(int i=0;i<A.size();i++)
sum= sum+A.get(i);
return sum;
}
int max_sum=0;
for(int i=0;i<A.size();i++){
if((max_sum<suffix(A.size()-(B-i))+prefix(i-1)) ){
max_sum=suffix(A.size()-(B-i))+prefix(i-1);
}
}
return max_sum;
}
int prefix_sum=0;
int prefix(int a) {
for(int p=0;p<a+1;p++){
c=A;
prefix_sum=prefix_sum + c.get(p);
}
return prefix_sum;
}
int suffix_sum=0;
int suffix(int b){
c=A;
for(int q=b;q<c.size();q++){
suffix_sum=suffix_sum+c.get(q);
}
return suffix_sum;
}
}
I am getting runtime error, I have tried to implement the suffix and prefix methods which return the sum from the index[ 0, i] and sum from [i, N-i] respectively, then in the solve function I am trying to find the sum of prefix [a-1] +suffix[N-(b-a)] and find out the maximum sum, the syntax is completely correct, there is something wrong with the logic I assume, please help me find the correct solution by correcting this code instead of providing an alternative method
package com.array;
import java.util.Arrays;
import java.util.List;
public class PickFromBothSides {
public static void main(String[] args) {
Integer[] arr = { 5, -2, 3, 1, 2 };
System.out.println(solve(Arrays.asList(arr), 3));
}
public static int solve(List<Integer> A, int B) {
int n = A.size();
int result = 0;
for (int i = 0; i < B; i++) {
result += A.get(i);
}
int sum = result;
for (int i = 0; i < B; i++) {
sum -= A.get(B - 1 - i);
sum += A.get(n - 1 - i);
result = Math.max(result, sum);
}
return result;
}
}
Runtime O(n)
Space complexity O(1)
You are declaring int prefix_sum=0; and int suffix_sum=0; as fields, not as local variables of the respective methods.
You are calling suffix(A.size()-(B-i)) so with your example that is 10 - (4 -i) which is 6 + i. You iterate through i being in the range {0, ..., 10} so the value 6 + i will be all the numbers 6 through 16. You cannot index in the array above 9, so you get an exception.
You need to change
for(int i=0;i<A.size();i++){
to
for(int i=0; i <= B; i++){
because you are trying to ask each iteration "how many numbers are taken from the beginning"? 0, 1, 2, 3 or 4 if B is 4
Other upgrades:
You are calling suffix(A.size()-(B-i))+prefix(i-1)) twice in a row. Call it only once, store it in a variable and reuse.
You are calling prefix(i-1) but inside prefix() you are using the parameter a as a + 1. You don't need to subtract one and add one to the same thing

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.

Java - variable in method not erased after call

I really need to explain behavior of code I have created.
Variable preyPred here: private static double[] preyPredLV(double[] preyPred, double[] a, double[] b, int n) is local for method preyPredLV or not?
Because, when I manipulate it during calling of the method, and then I call the method again for different n, it does not assign preyPredDefault as value of preyPred, but it uses its own value from previous call. Shouldn't its previous value be discarded when method returns output value and shouldn't be the new value assigned during next call? Can someone please explain? Thank you
Whole code:
public class Main {
public static void main(String[] args) {
double[] preyPredDefault = {300, 20};
double[] a = {0.1, 0.01};
double[] b = {0.01, 0.00002};
int n = 1;
double[] result = preyPredLV(preyPredDefault, a, b, n);
System.out.println("After "+n+" generations: Hares = "+result[0]+" and Lynx = "+result[1]);
n = 2;
result = preyPredLV(preyPredDefault, a, b, n);
System.out.println("After "+n+" generations: Hares = "+result[0]+" and Lynx = "+result[1]);
}
private static double[] preyPredLV(double[] preyPred, double[] a, double[] b, int n) {
double[] preyPredOld = new double[2];
System.out.println("n = "+n);
System.out.println("preyPred[0] = "+preyPred[0]);
System.out.println("preyPred[1] = "+preyPred[1]);
for(int iteration = 0; iteration < n; iteration++){
preyPredOld[0] = preyPred[0];
preyPredOld[1] = preyPred[1];
preyPred[0] = preyPredOld[0] * (1 + a[0] - a[1]*preyPredOld[1]);
preyPred[1] = preyPredOld[1] * (1 - b[0] + b[1]*preyPredOld[0]);
}
return preyPred;
}
}
Result:
n = 1
preyPred[0] = 300.0
preyPred[1] = 20.0
After 1 generations: Hares = 270.00000000000006 and Lynx = 19.92
n = 2
preyPred[0] = 270.00000000000006
preyPred[1] = 19.92
After 2 generations: Hares = 219.31183648512007 and Lynx = 19.726535847029762
Arrays in Java are not passed as a copy. They are passed as a reference to the array, which is then shared between caller and method.
So if you update the array from within the method, this is an in-place update, and the changes will be visible to whoever else has a reference to that array.
If you want to avoid that, make a "defensive copy" (using Arrays.copyOf) and make changes only to that.
You are passing a reference of the preyPredDefault array to your preyPredLV method, and your method updates this array via the reference you pass. Thus your method modifies the content of that array.
If you don't want preyPredLV to update that array, you can pass it a copy of the array.
double[] result = preyPredLV(Arrays.copyOf(preyPredDefault,preyPredDefault.length), a, b, n);

Can I swap two int[] using swap function in java?

I created a 2D array of int[]
Now, I want to swap two int[] inside of 2D array
I have this for my code:
swap(values[row][col], values[randomRow][randomCol]);
where values is a 2D array of int[].
so values[int][int] is a int[];
I get an error message like this:
Error: The method swap(int[], int[]) is undefined for the type ShufflePic
How should I fix this?
Thanks a lot!
Java is pass-by-value. You cannot swap values like this.
Instead use this approach :
void swap(int[][] array, int row1, int col1, int row2, int col2) {
int temp = array[row1][col1];
array[row1][col1] = array[row2][col2];
array[row2][col2] = temp;
}
Now you can call swap(...) method to swap the values
swap(values, row, col, randomRow, randomCol);
mybe your method should looks like
swap(int[] arryFirst, int arryFirstRow, int arryFirstCol, int[] arrySec, int arrySecRow, int arrySecCol)
Basically, this finds the indices and swaps according to these indices. Try printing the items in the list after swapping. Of course, this technique could also be implemented for 2D arrays, but I'll leave that as a challenge for you.
public class Test {
static int[] list = {4, 5, 6, 3, 1, 2};
public static void main(String[] args) {
swap(6, 2); // test swap
}
public static void swap(int a, int b) {
int a_index = 0;
int b_index = 0;
for (int i = 0; i < list.length; i++) {
if (list[i] == a) a_index = i;
if (list[i] == b) b_index = i;
}
list[a_index] = b;
list[b_index] = a;
}
}
I created a 2D array of int[]
You did indeed do that, but you probably wanted to create a 2D array of int, not int[].
values[row][col] = 5 //2d int array
values[row][col] = new int[length] //3d int array. Probably not what you intended
Once you fix that, the other answers about passing by value should work for you.
EDIT:
If that's what you want, then this method should work:
public void swapArrays(int[][][] arr, int row1, int col1, int row2, int col2) {
int[] temp = arr[row1][col1];
arr[row1][col1] = arr[row2][col2];
arr[row2][col2] = temp;
}
You would then call this with:
swapArrays(values, row, col, randomRow, randomCol);
The reason you were getting the error is because you hadn't defined a swap function which takes in two arrays. However, even if you had, it wouldn't have functioned properly because of the pass-by-value, pass-by-reference thing. (Google it for more info on that.)
With my proposed method, it will have a reference to the entire array, enabling it to change its values. If you just passed in values[row][col], the method would only see the value stored at that index, but not access to the values array.

Android Function to return an array directly into variables

I saw that javascript has something similar.
Is it possible to do something like this in Android?
I know how to do it with array names, my question is about returning and assigning directly from the variables that compose the arrays.
private int[] calcHead() {
int i;
int j;
int k;
// Do stuff
return {i, j, k}; <-- is this possible? (I am getting error: "The Method must return a result of type int[]")
}
private void otherFunc(){
int a;
int b;
int c;
{a, b, c} = calcHead(); <-- is this possible?
}
This is a rather basic question:
Anyway :
public int[] foo() {
int i = 0;
int j = 0;
int k = 0;
return new int[]{i,j,k};
}
In answer to the second part of the question, instead of
{a, b, c} = calcHead();
you can do
a = b = c = calcHead();
although its not very elegant it would assign the return value to each variable...
Hope that helps!

Categories

Resources