JAVA Arrays - Need somebody to explain what this code does? - java

int temp;
for (int i = 0; i < numbers.length/2; i++) {
temp = numbers[i];
numbers[i] = numbers[numbers.length - 1 - i];
numbers[numbers.length - 1 - i] = temp;
So this is code in one of my labs but I don't understand it.
So first you declare int temp, but why? Shouldn't you declare a temp int array?
Then the second line is a loop that goes through the index and you /2 because you don't actually need to go through all values if you switch half, you switched all of them.
I don't understand the next two lines at all.
Thanks in advance.

Carefully step through the inside of the loop a couple times:
temp = numbers[i];
numbers[i] = numbers[numbers.length - 1 - i];
numbers[numbers.length - 1 - i] = temp
On your first pass i is 0
so start with an array like this:
[1,2,3,4,5]
if temp=numbers[0] then temp will be 1. numbers.length will be 5, so numbers.length-1-i will be 4. numbers[4] is 5. after you have done each line, repeat with i=1 then i=2. Examine your array when you are done (it will change).
just keep on going like that. It's better to figure it out for yourself than to be handed answers--much more fun :)

(1) You declare int temp to store the value of variables that are being swapped in the array, so when you overwrite one of the array elements, you still have the variable value. You don't need to use an entire array for this.
(2) The code you don't understand swaps the array values at numbers[i] and numbers[numbers.length - 1 - i], using temp as a placeholder.

All this code does is reverse an array. It goes all the way to array.length/2 (other wise if it went to length it would swap, then swap back doing nothing).
The temp doesn't need to be an array because it's just a variable to hold on to old values while the swap is happening.
The final two lines of the code is where the swap actually happens.
So if you provide input of {1, 2, 3, 4, 5} it will output {5, 4, 3, 2, 1}.
If you look at when i =0:
numbers[0] = 1, numbers[4] = 5,
temp will become 1, then numbers[0] will become 5, then numbers[4] will become the value of temp (1).
So after that first iteration of the loop, your array will look like this:
{5, 2, 3, 4, 1}

Don't worry too much about the declaration. Let's focus on the lines you don't understand at all. The three lines inside the loop are as follows:
temp = numbers[i];
This puts the value of the ith element of the array into temp (so we can get to it later).
numbers[i] = numbers[numbers.length - 1 - i];
This puts the value of the ith element from the end into the ith element.
numbers[numbers.length - 1 - i] = temp;
This puts the original value of the ith element into the ith element from the end.
That is, we iterate over the first half of the array, swapping elements with the opposite elements from the second half of the array. In other words, we are reversing the array.

Related

Printing a sub-array with built-in functions without using extra memory

Let's say I've an array:
int[] array = new int[] {0,1,2,3,4,5,6,7,8,9};
I want to print a sub-array of the above array starting from index i and ending at index j. For example, if i=3 & j=6, the sub-array to be printed would be:
[3, 4, 5, 6] or simply as 3 4 5 6
We can simply print the sub-array with a for loop as:
for (int k=i; k<=j; k++) System.out.print(array[k]+" ");
But I'm looking for a method to achieve this like Arrays toString() method.
So, we can use Arrays.copyOfRange() to create a copy of the desired sub-array and print it as:
int[] subArray1 = Arrays.copyOfRange(array, i, j+1);
System.out.println(Arrays.toString(subArray1));
There are few other ways to achieve this as well but all of them tend to use extra space to create a copy of the sub-array. Is there any method or way (except the above) to directly print the sub-arrays from the given indices without using extra memory?

How to initialise an int java array of size n initially empty?

In a function,I want to initialise a java array of max size n, which is empty initially.If I add 3 elements(say n>3) and return the array, the array should contain only the 3 elements and not 3 elements followed by (n-3) 0's.
//PSEUDO CODE
func(){
//Create array A of max size 5
A[0]=1;
A[1]=2;
A[2]=3;
return A;
}
main(){
int[] B=func();
//B.length should give 3
for (int i=0;i<B.length;i++){
print B[i];
}
/*Should print 1 2 3
and Not 1 2 3 0 0
*/
}
And I don't want to use array list.I want to use java array only.
Your problem seems to be that you only want to print the non-default values of the array. If your values are always different from zero, then you can just do:
for (int i=0;i<B.length;i++){
if (B[i] != 0){
print(B[i]);
}
}
However, if your values can also be zero, you can also keep a counter of how many values you currently have, and only print that many values:
int counter = 3; //the array might be {1, 2, 3, 0, 0}
for (int i=0; i<counter; i++){
print(B[i]); //will print "1 2 3"
}
The counter must be incremented everytime you add a value.
Both solutions are limited though, depending on how you access and use the array.
then u have to make the array dynamic by urself. Everytime u add an element to the array create a new array of size=no of elements (let u r adding the 3rd element then size of new array would be 3). take the elements from old array to the new one. Each time u add 1 element u have to follow this.

Counting Int Occurrences in an Array

I am trying to count the occurrences of integers in an array. I was able to get it to work by piecing together some code I found online but I don't really understand why its working. What I have is:
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[hand.length];
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
for (int i = 1; i < numOccurence.length; i++)
if (numOccurence[i] > 0)
System.out.println("The number " + i + " occurs " + numOccurence[i] + " times.");
The output is:
The number 2 occurs 2 times.
The number 3 occurs 1 times.
The number 4 occurs 2 times.
How is this code counting the number of occurrences properly? I don't see how its accomplishing this. Thank you in advance!
This is only working because you've a good luck. Try making the second element in the hand array as 5 and see what happens. Its because the number present at the current index of hand is taken as the index of array numOccurence. In case of a number greater than or equal to the length of the numOccurence, you'll get the ArrayIndexOutOfBoundsException.
Thereforce, you can better use a Map for this where the key would be the number and the value could be its count.
Something like this:-
Map<Integer, Integer> numOccurence = new HashMap<Integer, Integer>();
for (int i = 0; i < hand.length; i++) {
int cnt = 1;
if (numOccurence.containsKey(hand[i])) {
cnt = numOccurence.get(hand[i]);
cnt++;
}
numOccurence.put(hand[i], cnt);
}
This code does not really work. At least it does for the author's use case but probably not for yours.
Try with {2, 4, 99, 2, 4}; as hand and it will fail.
The author takes the number found in hand as the index of array numOccurence.
numOccurence has the following structure : {nb occ of 0; nb occs of 1;...; nb occs of 4}. Here 99 will be out of bounds.
When you create an array
int[] numOccurence = new int[hand.length];
it is populated by their default values. For primitive int this value is 0.
This will of course only work if hand contains numbers less than or equal to max index (length -1) of the array otherwise it's ArrayIndexOutOfBound for you mister!
Actually it's the same method for creating histogram for picture ;)
You create a table where you will gather the occurrence.
numOccurence[0] will stock the number of 0
numOccurence[1] will stock the number of 1
etc.
That's what is done by this
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
it adds 1 to the value in the case corresponding to the number hand[i]
so if you look at this step by step
first he will take hand[0] = 2
so he will put
numOccurence[2] = numOccurence[2] + 1 ;
which is same (but faster to write) as
numOccurence[2]++;
This kind of performing a count is called counting sort.
The advantage of counting sort is it's speed. The disadvantage is the memory requirements when sorting big numbers.
There is a bug in the code:
int[] numOccurence = new int[hand.length];
numOccurence needs to be as long as the highest number in the list (not the number of numbers in the list). Try changing one of the numbers to 15 and you will get an exception.
The code iterates through the given array hand. it takes each value encountered as an index into the array numOccurrence. for each number n in hand, this will happen exactly as often as n occurs in hand, and each time this happens, the nth element of numOccurrence will be incremented.
thus numOccurrence is effectively an array of counters (assuming that the array elements are initialized with 0).
drawbacks of this approach:
the number of counters allocated depends on the magnitude of numbers in your handarray.
if the numbers in your hand array are distributed sparsely, most of the allocated space is never used.
alternative
you could improve the code by sorting hands first. in the sorted array the indexes of all occurrences of a given number are contiguous, so you scan the sorted array once needing a single counter only to compile the frequencies.
First of all the code is wrong. You should set the size of numOccurence array to the max number value from hand array + 1. For example:
int[] hand = {2, 100};
int[] numOccurence[] = new int[101];
(you should obviously find max number programatically)
Now let's take a look at the algorithm.
It takes each number from hand array, treats it as a numOccurence index value and increments number at that index by 1 in hand array. Note that all elements of numOccurence array are 0 by default at the beginning.
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[5];
Steps:
i = 0 (nothing happens, because there is no 0 in hand array)
i = 1 (same situation as for 0)
i = 2 (there are two 2 numbers in hand array, so we do operation numOccurence[2] += 1 twice, which in result gives 0 + 1 + 1 = 2. So we got numOccurence[2] = 2)
it continues for all numbers from 0 to max number from hand array (here: 100).

Any O(n) algorithm for smoosh method?

I am trying to finish a smoosh() method which will takes an array of ints. On completion the array should still contains the same numbers but wherever the array had two or more consecutive duplicate numbers, they are replaced by one copy of the number. Hence,
after smoosh() is done, no two consecutive numbers in the array are the same.
Any unused elements at the end of the array are set to -1.
For example, if the input array is
[ 1 1 0 0 4 4 5 0 0 0 7 ]
it reads
[ 1 0 4 5 0 7 ]
after smoosh() completes.
The method signature is:
public static void smoosh(int[] ints)
I was able to do it like this:
for (int i=0; i<ints.length-1; i++) {
if (ints[i+1]==ints[i])
ints[i]=-1;
}
for (int i=0; i<ints.length-1; i++) {
if (ints[i]==-1) {
for (int j=i+1; j<ints.length; j++) {
if (ints[j]!=-1) {
//swap ints[j] and ints[i] and then break;
}
}
}
}
However, this will be O(n2) time (although almost in place).
I feel like there should be some O(n) in place method to do this but I can't figure out how.
Could anyone think of any O(n) in place algorithm? (Obviously if you make another array of the same size to help processing then you can get O(n) easily but that's not what I am looking for since that's not in place...)
thanks!
Basically, as follows. This O(n)-time, O(1)-space "algorithm" is actually Python code, since that's a very good language for teaching basic algorithms, as long as you avoid all the complex stuff, like lambdas.
I'm actually using it to teach my 8yo son at the moment as he's expressed an interest in what I do all day at work.
array = [1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]
print array
count = len (array)
last = array[0] - 1
toidx = 0
for fromidx in range (0, count):
if array[fromidx] != last:
array[toidx] = array[fromidx]
toidx = toidx + 1
last = array[fromidx]
while toidx < count:
array[toidx] = -1
toidx = toidx + 1
print array
The output of this is:
[1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]
[1, 0, 4, 5, 0, 7, -1, -1, -1, -1, -1]
as your specification ask for.
It basically runs two indexes through the array, the fromix index advances by one no matter what. The toidx index only advances if the value at fromidx is different to the last one transferred. The initial value of the last one transferred is set to something different to the first element, so as to ensure the first element is transferred.
In other words, on each iteration where that condition is true, the value at the from index is copied to the toidx index, the toidx index is incremented, and the last value is updated. If the value at fromidx is the same as the last transferred, the toidx index is not updated.
Then, at the end, all the remaining values are set to -1.
Since your specs call for the rest of the array to be populated with -1, that's what I've done in the above code.
However, your sample result does not contain the negative values so, on the off chance that you need the array truncated rather than filled with -1, you basically replace the while loop at the end with an array truncation, so that its size is now toidx.
In Python, you could do that with something like:
array = array[0:toidx]
There's no need for your inner loop. You just have to keep track of what the last value you visited was, then start skipping until you find a 'new' number. e.g. in pseudo code
previous = null;
newarray = array();
newpos = 0;
for (i = 0; i < oldarray.length; i++) {
if (oldarray[i] == previous) {
continue; // got a duplicate value, so skip it.
} else {
newarray[newpos++] = oldarray[i];
previous = oldarray[i];
}
}
for (i = newpos; i < oldarray.length; i++) {
newarray[i] = -1; // fill in any empty slots
}
Now you're down to O(n).
If you use a LinkedList instead, you could use a ListIterator for the loop, storing the value of the previous value in the list and calling ListIterator.remove if it equals the current value.

In java, what is the best way to sort an integer array if only the last number item is displaced?

It's an array of integers.
It was created this way:
No element is repeated. Every time an element is added, its number is the next available integer, from 0 onwards. This way, if you add 6 elements in a row, they will be 0, 1, 2, 3, 4, 5, in that order. If you delete an element, the array shrinks, and a 'hole' is left between two of the elements, they are no longer consecutive because of that gap: 0, 1, 3, 4, 5. Then comes the problem: if you add a new element, it gets added to the end, but has the next available integer. So, the array is now 0, 1, 3, 4, 5, 2. It needs to be sorted, so the 2 can occupy its place between the 1 and the 3.
What is the best way to do it? I have thought of several methods. The list is nearly ordered, and it has the property that, when it is ordered, every element is equal to or greater than its index in the array. I am currently doing a bubble sort (don't laugh), i think quick sort is overkill, i dont want to go recursive or use temporary arrays, and i dont want to change the add-element method (which adds the element at the end), so it must be sorted immediately after adding an element (so only the last element is out of place)
Take the last element and do a insertion sort.
Maybe you should look at the idea of Insertion Sort.
You do not need to sort the whole list, just insert the last element in order:
int pos = array.length - 1:
while (pos > 0 && array[pos] < array[pos - 1]) {
tmp = array[pos - 1];
array[pos - 1] = array[pos];
array[pos] = tmp;
pos--;
}
What about using a java.util.BitSet instead? You'd get constant-time insertion and removal (finding the first free place will still take O(n) though). And with nextSetBit, you can iterate over the set in ascending order. With nextClearBir(), finding the first unused index becomes trivial, too.
//based on gpeche's code
int pos = array.length - 1;
int val = array[pos];
while (pos > 0 && array[pos-1] > val) {
array[pos] = array[pos - 1];
pos--;
}
array[pos] = val;
Are you constrained to use an array? If not, then just use a TreeSet. Why write your own sort algorithm when you can make use of standard libraries that perform this function already? It has guaranteed O(log(n)) time for insertions.
import java.util.TreeSet;
TreeSet<Integer> sortedSet = new TreeSet<Integer>();
// Add integers as needed
sortedSet.add( someInt );
// If you need an array at the end
Integer[] array = sortedSet.toArray( new Integer[sortedSet.size()] );

Categories