Passing an Array and sort - java

Good day guys, I am trying to sort here using an array, Check my codes
public int[] Sort(int[] arr) {
int[] value = arr;
int min, temp, out;
for (out = 0; out < value.length - 1; out++) {
for (min = out + 1; min < value.length; min++) {
if(value[out] > value[min]){
temp = value[min];
value[min] = value[out];
value[out] = temp;
}
}
}
return value;
}
The problem here is I pass the array 'arr' value to the array 'value' and sort the 'value' array then the output is what i expect, he sorted the number, but the problem is, when i tried to return the 'arr' array it also return a sorted value even though i didn't tried to sort it .. is it a bug or just my ugly coding ?

When you make the assignment int[] value = arr, you give value the same reference as arr. This means that assigning, for example, value[1] will affect the original array. If you want to return a new sorted array without affecting the original one, then you can try making a copy of it:
public int[] Sort(int[] arr) {
int[] value = new int[arr.length];
System.arraycopy(arr, 0, value, 0, arr.length);
// ...
return value;
}

Your variables arr and value both point to the same array.
Apparently you thought your sorting manipulations were applied to a second array. But, no, you were changing the original array.
Learn about reference variables. The two variables are not an array themselves, they are a pointer to an array that lives elsewhere in memory. So there are three “things” in play here. One reference variable, another reference variable, and an array. All three are distinct from one another.
When these reference variables go out of scope or get assigned to another object, so no more reference variables point to the array object, then the array object becomes a candidate for garbage collection.
Seems that you want to copy the array to another array. Stack Overflow has many Questions and Answers on the topic of copying an array in Java for you to study. Like this one.

Here is another approach, You'd clone the array and sort
int[] value = arr.clone();
any operation on the cloned array wont affect the original array.
Ex
int[] arr = { 1, 4, 3 };
int[] a = arr.clone();
a[2] = 5;
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(a));
output
[1, 4, 3]
[1, 4, 5]

Related

List with primitive array versus List with Object array

I have the below piece of code for swapping.
public static <E> void swap(List<E> list, int i, int j){
E temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
Now when I use List backed by Integer array like below
Integer[] ar = new Integer[]{1,2};
swap(Arrays.asList(ar),1,0);
It works fine and gives output as [2,1]
But I use List backed by int array like below
int[] ar = new int[]{1,2};
swap(Arrays.asList(ar),1,0);
It hrows ArrayIndexOutOfBounds exception. I don't understand why this is happening. List should treat int element as object only. Little help please.
Here is what is happening. Your current code is actually creating a List<Object>, which happens to contain just a single int[], not a list of actual integers:
int[] ar = new int[]{1,2};
List<Object> list = Arrays.asList(ar);
The reason for the ArrayIndexOutOfBounds exception is that the list you pass in to the swap method has only one entry, at index zero.
In any case, it is not possible to use Arrays.asList to directly convert an array of primitives to a list of some boxed type. The first version of your code is correct, and is what you should be using:
Integer[] ar = new Integer[] {1, 2};
swap(Arrays.asList(ar), 1, 0);

Storing a sorted array in Java? [duplicate]

I have an array a which is constantly being updated. Let's say a = [1,2,3,4,5]. I need to make an exact duplicate copy of a and call it b. If a were to change to [6,7,8,9,10], b should still be [1,2,3,4,5]. What is the best way to do this? I tried a for loop like:
for(int i=0; i<5; i++) {
b[i]=a[i];
}
but that doesn't seem to work correctly. Please don't use advanced terms like deep copy, etc., because I do not know what that means.
You can try using System.arraycopy()
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );
But, probably better to use clone() in most cases:
int[] src = ...
int[] dest = src.clone();
you can use
int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();
as well.
If you want to make a copy of:
int[] a = {1,2,3,4,5};
This is the way to go:
int[] b = Arrays.copyOf(a, a.length);
Arrays.copyOf may be faster than a.clone() on small arrays. Both copy elements equally fast but clone() returns Object so the compiler has to insert an implicit cast to int[]. You can see it in the bytecode, something like this:
ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
Nice explanation from http://www.journaldev.com/753/how-to-copy-arrays-in-java
Java Array Copy Methods
Object.clone(): Object class provides clone() method and since array
in java is also an Object, you can use this method to achieve full
array copy. This method will not suit you if you want partial copy of
the array.
System.arraycopy(): System class arraycopy() is the best way to do
partial copy of an array. It provides you an easy way to specify the
total number of elements to copy and the source and destination array
index positions. For example System.arraycopy(source, 3, destination,
2, 5) will copy 5 elements from source to destination, beginning from
3rd index of source to 2nd index of destination.
Arrays.copyOf(): If you want to copy first few elements of an array or
full copy of array, you can use this method. Obviously it’s not
versatile like System.arraycopy() but it’s also not confusing and easy
to use.
Arrays.copyOfRange(): If you want few elements of an array to be
copied, where starting index is not 0, you can use this method to copy
partial array.
I have a feeling that all of these "better ways to copy an array" are not really going to solve your problem.
You say
I tried a for loop like [...] but that doesn't seem to be working correctly?
Looking at that loop, there's no obvious reason for it not to work ... unless:
you somehow have the a and b arrays messed up (e.g. a and b refer to the same array), or
your application is multi-threaded and different threads are reading and updating the a array simultaneously.
In either case, alternative ways of doing the copying won't solve the underlying problem.
The fix for the first scenario is obvious. For the second scenario you will have to figure out some way of synchronizing the threads. Atomic array classes don't help because they have no atomic copy constructors or clone methods, but synchronizing using a primitive mutex will do the trick.
(There are hints in your question that lead me to think that this is indeed thread related; e.g. your statement that a is constantly changing.)
You can try using Arrays.copyOf() in Java
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
All solution that call length from array, add your code redundant null checkersconsider example:
int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
//What if array a comes as local parameter? You need to use null check:
public void someMethod(int[] a) {
if (a!=null) {
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
}
}
I recommend you not inventing the wheel and use utility class where all necessary checks have already performed. Consider ArrayUtils from apache commons. You code become shorter:
public void someMethod(int[] a) {
int[] b = ArrayUtils.clone(a);
}
Apache commons you can find there
You can also use Arrays.copyOfRange.
Example:
public static void main(String[] args) {
int[] a = {1,2,3};
int[] b = Arrays.copyOfRange(a, 0, a.length);
a[0] = 5;
System.out.println(Arrays.toString(a)); // [5,2,3]
System.out.println(Arrays.toString(b)); // [1,2,3]
}
This method is similar to Arrays.copyOf, but it's more flexible. Both of them use System.arraycopy under the hood.
See:
https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Arrays.java?av=f
If you must work with raw arrays and not ArrayList then Arrays has what you need. If you look at the source code, these are the absolutely best ways to get a copy of an array. They do have a good bit of defensive programming because the System.arraycopy() method throws lots of unchecked exceptions if you feed it illogical parameters.
You can use either Arrays.copyOf() which will copy from the first to Nth element to the new shorter array.
public static <T> T[] copyOf(T[] original, int newLength)
Copies the specified array, truncating or padding with nulls (if
necessary) so the copy has the specified length. For all indices that
are valid in both the original array and the copy, the two arrays will
contain identical values. For any indices that are valid in the copy
but not the original, the copy will contain null. Such indices will
exist if and only if the specified length is greater than that of the
original array. The resulting array is of exactly the same class as
the original array.
2770
2771 public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772 T[] copy = ((Object)newType == (Object)Object[].class)
2773 ? (T[]) new Object[newLength]
2774 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775 System.arraycopy(original, 0, copy, 0,
2776 Math.min(original.length, newLength));
2777 return copy;
2778 }
or Arrays.copyOfRange() will also do the trick:
public static <T> T[] copyOfRange(T[] original, int from, int to)
Copies the specified range of the specified array into a new array.
The initial index of the range (from) must lie between zero and
original.length, inclusive. The value at original[from] is placed into
the initial element of the copy (unless from == original.length or
from == to). Values from subsequent elements in the original array are
placed into subsequent elements in the copy. The final index of the
range (to), which must be greater than or equal to from, may be
greater than original.length, in which case null is placed in all
elements of the copy whose index is greater than or equal to
original.length - from. The length of the returned array will be to -
from. The resulting array is of exactly the same class as the original
array.
3035 public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036 int newLength = to - from;
3037 if (newLength < 0)
3038 throw new IllegalArgumentException(from + " > " + to);
3039 T[] copy = ((Object)newType == (Object)Object[].class)
3040 ? (T[]) new Object[newLength]
3041 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042 System.arraycopy(original, from, copy, 0,
3043 Math.min(original.length - from, newLength));
3044 return copy;
3045 }
As you can see, both of these are just wrapper functions over System.arraycopy with defensive logic that what you are trying to do is valid.
System.arraycopy is the absolute fastest way to copy arrays.
For a null-safe copy of an array, you can also use an optional with the Object.clone() method provided in this answer.
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
I had a similar problem with 2D arrays and ended here.
I was copying the main array and changing the inner arrays' values and was surprised when the values changed in both copies. Basically both copies were independent but contained references to the same inner arrays and I had to make an array of copies of the inner arrays to get what I wanted.
This is sometimes called a deep copy. The same term "deep copy" can also have a completely different and arguably more complex meaning, which can be confusing, especially to someone not figuring out why their copied arrays don't behave as they should. It probably isn't the OP's problem, but I hope it can still be helpful.

Unsorted Array and Sorted Array are returned with their elements in the same order

I'm not sure what's going on here, I've got two array variables, one of them has its elements unsorted, while the other one is meant to be a copy in order to maintain both the unsorted and sorted arrays instead of just using one and losing the information in the other one.
public static void main(String[] args){
int[] unsortedArray;
int[] sortedArray;
boolean continueProgram = true;
Scanner inputScanner = new Scanner(System.in);
String answer = new String();
while (continueProgram == true) {
unsortedArray = buildArray();
sortedArray = unsortedArray;
System.out.println(Arrays.toString(unsortedArray));
quickSort(sortedArray, 0, sortedArray.length - 1);
System.out.println(Arrays.toString(unsortedArray));
returnPositions(sortedArray, unsortedArray);
Here's my code, I've used a quicksort to sort the elements, but only on the variable sortedArray, not in unsorted array, so I don't know why it is returned as if it were sorted when I it is to be printed.
It looks like you're printing the unsorted array both times. Starting where you have your first println, try:
System.out.println(Arrays.toString(unsortedArray));
quickSort(sortedArray, 0, sortedArray.length - 1);
System.out.println(Arrays.toString(sortedArray));
returnPositions(sortedArray, unsortedArray);
Create a copy of your unsorted array before using it to sort:
sortedArray = new int[unsortedArray.length];
System.arraycopy( unsortedArray, 0, sortedArray, 0, unsortedArray.length );
When you write:
sortedArray = unsortedArray;
you aren't actually creating a copy of the array, you're just setting both variables to point to the same array - which you then sort.

Why should we copy an ArrayList in some recursive alogrithms?

http://oj.leetcode.com/problems/subsets-ii/
Given a collection of integers that might contain duplicates, S, return all possible subsets.
Note:
* Elements in a subset must be in non-descending order.
* The solution set must not contain duplicate subsets.
For example,
If S = [1,2,2], a solution is:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
The answer is:
public class Solution {
public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> tmp = new ArrayList<Integer>();
Arrays.sort(num);
sub(num, 0, tmp, ans);
return ans;
}
public void sub(int[] num, int k, ArrayList<Integer> tmp, ArrayList<ArrayList<Integer>> ans) {
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);
ans.add(arr);
for (int i = k; i < num.length; i++) {
if (i != k && num[i] == num[i-1]) continue;
tmp.add(num[i]);
sub(num, i+1, tmp, ans);
tmp.remove(tmp.size()-1);
}
}
}
I don't know why
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);
ans.add(arr);
But not directly:
ans.add(tmp);
If you just want to print out the results, since you remove any element you added after the recursive call, tmp should look exactly the same at both the start and the end of the function, so it shouldn't make any difference (your way would be preferred as it doesn't copy the ArrayList at each step).
But the problem comes in when you add the results to ans.
If you use your way, there would only be a single ArrayList floating around - you'd just be adding it to ans multiple times.
Note that adding it to ans doesn't actually create a copy of it, it just adds a reference to the ArrayList to ans. So changing the original after it's been added also changes that element of ans.
Live demo showing the correct result by printing them out and the incorrect results in the returned array.
Directly adding it will make arr contain/be the same ArrayList instance as tmp. Down in your loop, when you are altering tmp, you would also be altering arr, which isn't your desired procedure.
Reason for not using
ans.add(tmp);
Since tmp is a method argument, so java passes a reference to the ArrayList by value.
So tmp actually a reference to a List, not a List.
So you need to create an ArrayList object with and add that object to ans
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);
ans.add(arr);
If you use ans.add(tmp), then the arrayList which tmp points to will be added to ans, and if any modifications are made later in the code to tmp, then the contents of the element which you added to ans will also change, since both will point to same memory block.

How to create a nested array of arbitrary depth in java?

I am trying to create an array of arrays of arrays etc..., except I don't know how many nested levels deep it needs to be until runtime.
Depending on the input, I might need either int[], int[][], int[][][][][][], or anything else. (For context, I am trying to construct an N-dimensional grid for a cellular automaton, where N is passed as a parameter.)
I don't have any code for you because I have no idea how to go about this; I suspect is not possible at all using just arrays. Any help, or alternative solutions, would be appreciated.
You could do this with an Object[], limiting its members to either Object[] or int[].
For example, here's an array that goes three levels deep in one part, and two levels deep in another:
Object[] myarray = new Object[] {
new Object[] { new int[] { 1, 2 },
new int[] { 3, 4 }},
new int[] { 5, 6 }
};
After you've created it, you may want to access members. In your case, you know the depth N up front, so you know at what depth to expect an Object[] and at what depth to expect an int[].
However, if you didn't know the depth, you could use reflection to determine whether a member is another Object[] level or a leaf int[].
if ( myarray[0] instanceof Object[] ) {
System.out.println("This should print true.");
}
EDIT:
Here's a sketch [untested so far, sorry] of a method that access a member of an array of known depth, given an array of indices. The m_root member can be an Object[] or an int[]. (You could relax this further to support scalars.)
public class Grid {
private int m_depth;
private Object m_root;
...
public int get( int ... indices ) {
assert( indices.length == m_depth );
Object level = m_root;
for ( int i = 0; i + 1 < m_depth; ++i ) {
level = ((Object[]) level)[ indices[i] ];
}
int[] row = (int[]) level;
return row[ indices[m_depth - 1] ];
}
}
This should be achievable using Object[], since arrays are objects:
int[] arr = {1,2,3};
int[] arr2 = {1,2,3};
int[] arr3 = {1,2,3};
int[] arr4 = {1,2,3};
Object[] arr5 = {arr, arr2}; // basically an int[][]
Object[] arr6 = {arr3, arr4}; // basically an int[][]
Object[] arr7 = {arr5, arr6}; // basically an int[][][]
// etc.
Note that one array doesn't have to contain arrays of the same dimensions:
Object[] arr7 = {arr5, arr};
To prevent this (and to allow for easier access to the data), I suggest writing a class which has an Object member (which will be your int[] or Object[]) and a depth variable and some nice functions to give you access to what you want.
ArrayLists will also work:
ArrayList array = new ArrayList();
array.add(new ArrayList());
array.add(new ArrayList());
((ArrayList)array.get(0)).add(new ArrayList());
// etc.
As your N increases going with nested arrays becomes less and less advantageous, especially when you have a grid structure. Memory usage goes up exponentially in N with this approach and the code becomes complex.
If your grid is sparsely populated (a lot of cells with the same value) you can instead have a collection of Cell objects where each of these holds a coordinate vector and the integer value of the cell. Every cell that is not in the collection is assumed to have a default value, which is your most common value.
For faster access you can use for example a k-d tree (https://en.wikipedia.org/wiki/K-d_tree) but that depends a bit on your actual use-case.
#Andy Thomas explains how to do this using Object[] for the higher levels of the multidimensional array. Unfortunately, this means that the types are not correct to allow indexing, or indeed to allow element access without typecasts.
You can't do this:
Object[] array = ...
int i = array[1][2][3][4];
To get types that allow you to do the above, you need to create an object whose real type is (for example) int[][][][].
But the flipside is that it is not really practical to use that style of indexing for N dimensional arrays where N is a variable. You can't write Java source code to do that unless you place a bound on N (i.e. up to 5) and treat the different cases individually. That becomes unmanageable very quickly.
You can use Java reflection as Arrays are objects.
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
Class<?> intClass = int.class;
Class<?> oneDimensionalArrayClass = Class.forName("[I");
Object oneDimensionalIntArray1 = Array.newInstance(intClass, 1);
Array.set(oneDimensionalIntArray1, 0, 1);
Object oneDimensionalIntArray2 = Array.newInstance(intClass, 1);
Array.set(oneDimensionalIntArray2, 0, 2);
Object oneDimensionalIntArray3 = Array.newInstance(intClass, 1);
Array.set(oneDimensionalIntArray3, 0, 3);
Object twoDimensionalIntArray = Array.newInstance(oneDimensionalArrayClass, 3);
Array.set(twoDimensionalIntArray, 0, oneDimensionalIntArray1);
Array.set(twoDimensionalIntArray, 1, oneDimensionalIntArray2);
Array.set(twoDimensionalIntArray, 2, oneDimensionalIntArray1);
System.out.println(Array.get(Array.get(twoDimensionalIntArray, 1), 0));
}
The class Array with its static methods gives access on items while you can specify the dimension of your arrays with the number of leading "[".
The whole construct of multi-dimensional arrays is just the compiler doing some work for you on a big block of memory (ok as some have commented in java this is multiple blocks of memory). One way to deal with the problem you face is to use nested arraylists at runtime. Another (more performant) way is to just allocate a single-dimensional array of the size you need and do the indexing yourself. You could then hide the indexing code in a method that was passed all the details like an array de-reference.
private int[] doAllocate(int[] dimensions)
{
int totalElements = dimensions[0];
for (int i=1; i< dimensions.length; i++)
{
totalElements *= dimensions[i];
}
int bigOne = new int[totalElements];
return bigOne;
}
private int deReference(int[] dimensions, int[] indicies, int[] bigOne)
{
int index = 0;
// Not sure if this is only valid when the dimensions are all the same.
for (int i=0; i<dimensions.length; i++)
{
index += Math.pow(dimensions[i],i) * indicies[dimensions.length - (i + 1)];
}
return bigOne[index];
}
Fields like you wrote above a checked and created by the compiler. If you want a dynamic data structure during runtime you could create your own data structure. Search for Composite Pattern. A small snippet should show you how it works:
interface IGrid {
void insert(IGrid subgrid);
void insert(int[] values);
}
class Grid implements IGrid {
private IGrid subgrid;
void insert(IGrid subgrid) {this.subgrid = subgrid;}
void insert(int[] values) {/* Do nothing */}
}
class SubGrid implements IGrid {
private int[] values;
void insert(IGrid subgrid) {/* Do nothing */}
void insert(int[] values) {this.values = values;}
}
You could simply create a Subgrid for int[] or a Grid with a Subgrid for int[][]. It's only a rudimental solution, you would have to create some code for working on your automaton's levels and values. I would do it this way. Hope it will help :) And look forward for more solutions^^

Categories