How exactly do arrays and for loops work together? - java

I understand that arrays are used to store values but when they are used with for loops I loose track of what is happening. I know that the output is 100 because I ran it in the terminal but what I need to understand is that how did it get 100 from using the for loops and the arrays because I'm not sure if it uses all three values or just the first one. Thanks in advance
Here is the problem:
public class arrays {
public static void main (String[] args) {
int[] a1 = {1, 1, 3};
mystery(a1);
}
public static void mystery(int[] a) {
for (int i = 1; i < a.length - 1; i++) {
a[i] = (a[i - 1] + a[i + 1]) /2;
}
}
}

Not entirely sure what the question you're trying to ask is but - to try and help - does it help that each time a[i] is called, it takes the value of i (also the iteration number) at each instance and uses that to find the relevant array index - which is then used for the rest of the computation.

try to add this method for tracing.
public class arrays{
public static void main(String[] args) {
int[] a1 = {1, 1, 3};
mystery(a1);
}
public static void mystery(int[] a) {
for (int i = 1; i < a.length - 1; i++) {
a[i] = (a[i - 1] + a[i + 1]) /2;
printArray(a);
}
public void printArray(int[] arr){
for(int i=0;i<arr.length;i++){
System.out.println("array[" + i + "] is now " + arr[i]);
}
}
EDIT: So what's going on back-stage?
for loop initializes i as 1.
a[1] (previously '1') is changed into (a[0] + a[2])/2 = (1 + 3)/2 = 2)
i is incremented by 1
i does not meet the condition (i < a.length - 1) because i = 2 and (a.length - 1) = (3 - 1) = 2 (2 is not less than 2, its equal to 2)
loop terminates and so is the program.
I think what you're missing is that i does not represent the index of the number 1 in your array, it is the index itself when used in the context of a[i] meaning "go to a, in index i..."

Your question is not clear. If you can provide question clearly, you will get great answers ! Anyways :
Try to think yourself.
Array position starts from "0" which is also called as the index of the array.
Here loop is going from value of
i =1 to i < the value of (array's length)-1 which is i < 2 as length of array = 3
So,
for(int i=1 ; i < a.length - 1; i++){
a[i] = (a[i - 1] + a[i + 1]) /2;
}
Now take initially value of i=1 and then run the code yourself in your mind :
1.. for i = 1,
**a[i] = (a[i - 1] + a[i + 1]) /2;**
gives a[1] = (a[0] + a[2])/2 ==> a[1] = (1+3)/2 ==> a[1] = 2
Important : you have given **i < a.length-1**
Now, a.length = 3 ok?
a.length -1 = 2 ok?
so i< a.length-1 will stop at i equals 1
So, your program will give {1,2,3} as for loop will iterate from i =1 to i=1 got it?
So only 1 value i.e. a[1] will gets changed.. a[0] and a[2] will remain same.

What happens when the method mistery(a1) is called:
1. int i is initialized to 1
2. The condition if i*a.length-1, which is (3-1), is checked; this condition is true;
3. because the condition at 2. is true, the code in the for loop is executed:
a[i] = (a[i - 1] + a[i + 1]) /2 => a[1] = (a[1-1]+a[1+1])/2 => a[1]=(a[0]+a[2])/2 =>
=> a[1]=(1+3)/2 => a[1]=2
4. after the code in the for loop is executed, i is incremented by 1, thus, the final stage of this for loop is executed: i++, i is equal to 2 right now.
5. Again, the for loop checks if the condition i<a.length-1, (3-1) is true; this time, the condition is false: i=2, 2 is not less than 2.
6. The for loop terminates its "existence", in this case the method mystery(a1) is fully executed.

Related

How can I create a java program to find the amount of consecutive numbers in an array?

I'm trying to make a Java program to find the number of consecutive numbers in an array. For example, if an array has the values, 1,8,10,4,2,3 there are 4 numbers that are consecutive (1,2,3,4). I've created this program, but I'm getting an error on lines 28 and 31 for ArrayIndexOutOfBoundsException, how do I fix the error? (I'm not even sure if the program I made will work if the errors are fixed). Note: I know there are many solutions online for this but I'm a beginner programmer, and I'm trying to do this a more simple way.
import java.util.Arrays;
class Main {
public static void main(String[] args) {
consec();
}
static void consec()
{
int[] nums = {16, 4, 5, 200, 6, 7, 70, 8};
int counter=0;
Arrays.sort(nums);
for (int i=0; i < nums.length; i++)
if (i != nums.length - 1)
System.out.print(nums[i] + ", ");
else
System.out.print(nums[i]);
for (int i=0; i < nums.length; i++)
for (int j=i; j < nums.length - i; j++)
if (nums[j + 1] - 1 == nums[j])
counter++;
else if (nums[j+1]==counter)
System.out.print("Consective amount is" + counter);
}
}
The issue for the exception lies within the access of nums[j + 1].
Note that j can be as large as nums.length - 1 due to the for loop.
Thus j + 1 can be nums.length which is an OutOfBounds array index.
Secondly I don't think your code solves the task - for example you only print a result if the number of consecutive numbers you've counted appears within the array. However I don't see how these things should correlate.
You can solve the problem like this:
for (int i = 1; i < nums.length; i++) {
if (nums[i-1] == nums[i] - 1) {
counter+= 2;
int j = i + 1;
while (j < nums.length && nums[j] - 1 == nums[j-1]) {
j++;
counter++;
}
i = j;
}
}
System.out.print("Consective amount is" + counter);
Note that the index i starts at 1, thus we can be assured that nums[i-1] exists.
If nums has only one element we should not run into any issues as the condition i < nums.length would not be fulfilled. We count two consequitves for every start of a sequence and one addition element for every following consequtive (while loop).
When the sequence ends we try finding a new sequence behind it by moving the index i to the end of the last sequence (j = i).
The above code will sum multiple distinct sequences of consequtive numbers. For example the array [17,2,20,18,4,3] has five consequitve numbers (2,3,4 and 17,18)
The algorithm has a time colpexity within O(n) as we either increase i or j by at least on and skip i to j after each sequence.
I would recommend re-thinking your approach to scanning over the array. Ideally you should only require one for-loop for this problem.
I personally created a HashSet of Numbers, which cannot hold duplicates. From there, you can iterate from 1 to nums.length-1, and check if nums[i] - 1 == nums[i-1] (ie: if they're consecutive). If they are equal, you can add both numbers to the HashSet.
Finally, you actually have the set of consecutive numbers, but for this question, you can simply return the size of the set.
I strongly recommend you attempt this problem and follow my explanation. If you simply require the code, this is the method that I came up with.
public static int countConsecutive(int[] nums) {
Set<Integer> consecutive = new HashSet<>();
if (nums.length <= 1)
return 0;
Arrays.sort(nums);
for (int i = 1; i < nums.length; i++) {
if (nums[i] != nums[i - 1] + 1)
continue;
consecutive.add(nums[i]);
consecutive.add(nums[i - 1]);
}
return consecutive.size();
}
Here is another approach where sorting is not necessary. It uses a BitSet. And as in your example, is presumes positive numbers (BitSet doesn't permit setting negative positions).
int[] values = {4, 3, 10, 11, 6, 1, 4, 8, 7};
set the corresponding bit positions based on the values.
BitSet bits = new BitSet();
for (int i : values) {
bits.set(i);
}
Initialize some values for output, starting bit position, and the set length.
BitSet out = new BitSet();
int start = 0;
int len = bits.length();
Now iterate over the bit set finding the range of bits which occupy adjacent positions. Those will represent the consecutive sequences generated when populating the original BitSet. Only sequences of two or more are displayed.
while (start < len) {
start = bits.nextSetBit(start);
int end = bits.nextClearBit(start+1);
if (start != end-1) {
// populate the subset for output.
out.set(start,end);
System.out.println(out);
}
out.clear();
start = end;
}
prints
{3, 4}
{6, 7, 8}
{10, 11}
If you just want the largest count, independent of the actual values, it's even simpler. Just use this in place of the above after initializing the bit set.
int len = bits.length();
int total = 0;
while (start < len) {
start = bits.nextSetBit(start);
int end = bits.nextClearBit(start + 1);
if (end - start > 1) {
total += end - start;
}
start = end;
}
System.out.println(total);

Codility: Missing Integer - Java SE 8

that, given a non-empty zero-indexed array A of N integers, returns the minimal positive integer (greater than 0) that does not occur in A. For example, given:
A[0] = 4
A[1] = 6
A[2] = 2
A[3] = 2
A[4] = 6
A[5] = 6
A[6] = 1
the function should return 4. Assume that:
in other words, A[K] = 2 for each K (0 <= K <= 50000), the given implementation works too slow, but the function would return 50,000
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1...100,000]
each element of array A is an integer the range [1..N]
My Answer is not yet successful! What is wrong with it? First let me state the obvious errors
return value - I return 4 in the first result and that was successful
but the second return is 1 that is not correct for the reason that
the expected result is 50,000
my code, which works but the only first result is correct and second is not.
import java.util.*;
class Solution {
int solution(int[] A) {
int[] AN = Arrays.stream(A).filter(n -> n > 0).distinct().sorted().toArray();
int N = AN.length;
int min = 1;
int i = 0;
while (i < N) {
min = i+1;
if (min == N) {
min = Math.max(min , Math.abs(i-N));
}
i++;
}
return min;
}
}
Note: In the example you gave, the missing integer is 3 and not 4
The performance issue is probably caused by using the distinct and sorted.
I'll create an algorithm based on the sorted array, so its complexity is O(n log n).
First we sort the array:
Arrays.sort(A);
Next we skip negative or zero numbers
while (i < A.length && A[i] <= 0)
i++;
If now the array is fully parsed or the current element A[i] is not 1, then the solution is 1.
If it's not the case, we continue parsing the array A, we initiliase missing variable to 1 and if the current element equals the missing element we increment i, or if the current element is equal missing + 1 we increment missing otherwise we stop, we found our missing integer.
In the end if our array is fully parsed without any mismatch between missing variable and A[i] then we increment missing.
The full code:
Arrays.sort(A);
int missing = 1;
int i = 0;
while (i < A.length && A[i] <= 0)
i++;
if (i < A.length && A[i] == 1) {
while (i < A.length) {
if (A[i] == missing) {
i++;
} else if (A[i] == missing + 1) {
missing++;
} else {
missing++;
break;
}
}
missing = i >= A.length ? missing + 1 : missing;
}
System.out.println(missing);

Why is there a difference between two similar implementations of a 'for' loop?

I'm trying to write an insertion sort method, and I have managed to finish it, but I don't understand why my first version cannot work correctly.
Here's my first attempt:
public static void insertionSort(int[] list) {
for (int i = 1; i < list.length; i++) {
int current = list[i];
for (int k = i - 1; k >= 0 && current < list[k]; k--) {
list[i] = list[k];
list[k] = current;
}
}
}
public static void main(String[] args) {
int[] list = {8, 22, 90, 10};
insertionSort(list);
}
My output for the above code is: 8, 10, 10, 22
But the answer would be correct if the inside for-loop, at line 5, is changed from: list[i] = list[k]; to: list[k + 1] = list[k];
To my understanding, k + 1 is equal to i, but it must be different in loop counting and I can't figure out how. I have tried many sets of input, and only values that lie between the range of the 2 first indexes (in this case 8 and 22) would be incorrect.
k + 1 is equal to i, but only in the first iteration of the inner for loop. int k = i - 1 is only run once per iteration of the outer for loop.
In the second iteration of the inner for loop, k is decremented but i is not. Therefore, k + 1 and i are not interchangeable inside the inner for loop.
// second iteration of the outer for loop, second iteration of the inner for loop:
list[i] = list[k]; // means "list[2] = list[0]
// whereas
list[k + 1] = list[k]; // means "list[1] = list[0]"

Understanding what java code prints

Hi guys I am fairly new to this and have a question about this code. I am unsure about how the output is what it is so if someone could explain it to a beginner I'd be grateful! This is the code:
public class NewClass{
public static int[] first(int[] a) { // Array {1,2,3} is passed as an argument
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++)
b[i] = a[a.length - 1 - i];
return b;
}
public static void second(int[] a) { // Use more descriptive names for you methods. If its aim is to reverse the array than call it reverseArray or something alike.
for (int i = 0; i < a.length/2; i++) { // a.length = 3, a.length/2 = 1; So this loop will run only once
int temp = a[i]; // temp = 4
a[i] = a[a.length - 1 - i]; // a[0] = a[3 - 1 - 0] (a[2]) equals a[0] = 6
a[a.length - 1 - i] = temp; // a[2] = temp equals a[2] = 4
} // Array has become {6,5,4} (So it's been reversed.)
}
public static void main(String[] args) {
int[][] matrix = {{1,2,3},{4,5,6}}; // Array of two elements, both elements refering to an other array with three elements
System.out.println(matrix.length); // This will print 2. It is a two dimensional array.
first(matrix[0]); // Calling the first method and passing the {1,2,3} array as argument. It does stuff to a copy of the array (int[] b), but the returned value is never used. Array {1,2,3} is untouched.
second(matrix[1]); // Same as with the first method
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) // You should use { }. It will make the code easier to read. Only line 25 is executed inside this nested loop
System.out.print(matrix[i][j]); // This will run 6 times (2 (outer loop) x 3 (nested loop)). It will print matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2]. Respectively 123 (next line) 456
System.out.println();
}
}
}
It outputs 2, then 1,2,3 and finally 6,5,4.
In your first function you are creating a new array. This array is returned however the value is never copied into the original. Therefore when printing the matrix the first loop will stay as 1, 2, 3. If you want this to change switch the line:
first(matrix[0]);
To:
matrix[0] = first(matrix[0]);
The second function takes the original array and loops once (since a.length is 3 and 3 / 2 = 1). During this loop it converts a[0] to a[a.length - 1 - i] or a[3 - 1 - 0]. It then switches a[a.length - 1 - i] or a[2] to temp which is a[0]. This will switch the first and last element in the array which are 6 and 4.
At first, your code is quite messy. Try to use the proper indentation (four spaces for each block). It makes the code easier to read (and you might have figured out the answer yourself).
public class NewClass{
public static int[] first(int[] a) { // Array {1,2,3} is passed as an argument
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++)
b[i] = a[a.length - 1 - i];
return b;
}
public static void second(int[] a) { // Use more descriptive names for you methods. If its aim is to reverse the array than call it reverseArray or something alike.
for (int i = 0; i < a.length/2; i++) { // a.length = 3, a.length/2 = 1; So this loop will run only once
int temp = a[i]; // temp = 4
a[i] = a[a.length - 1 - i]; // a[0] = a[3 - 1 - 0] (a[2]) equals a[0] = 6
a[a.length - 1 - i] = temp; // a[2] = temp equals a[2] = 4
} // Array has become {6,5,4} (So it's been reversed.)
}
public static void main(String[] args) {
int[][] matrix = {{1,2,3},{4,5,6}}; // Array of two elements, both elements refering to an other array with three elements
System.out.println(matrix.length); // This will print 2. It is a two dimensional array.
first(matrix[0]); // Calling the first method and passing the {1,2,3} array as argument. It does stuff to a copy of the array (int[] b), but the returned value is never used. Array {1,2,3} is untouched.
second(matrix[1]); // Same as with the first method
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) // You should use { }. It will make the code easier to read. Only line 25 is executed inside this nested loop
System.out.print(matrix[i][j]); // This will run 6 times (2 (outer loop) x 3 (nested loop)). It will print matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2]. Respectively 123 (next line) 456
System.out.println();
}
}
}
It outputs 2, then 1,2,3 and finally 6,5,4.

Java Quicksort why / where do the values change?

I'm learning Java in school right now and our latest topic are sort algorithms in Java. The one that I'm trying to understand is quicksort.
To understand how that algorithm sorts numbers in an array I decided to go through my code step for step in the Eclipse debugger window.
Now there was one step that I can not comprehend even after going through it what felt like hundreds of times.
My initial array is [10, 5, 3, 22, 11, 2]
When I go through the code the program starts by swapping 10 and 2, then 5 and 3 and then 2 and 2. At that point the value for i is 1 and the value for j is -1.
Now the way I see it is that there are three conditions
while(i<=j) Which returns false, because i = 1 and j = -1
if(left < j) Which returns false, because left = 0 and j = -1
if(i < right) Which also returns false, because i = 1 and right = 1
But to my surprise when the program gets to the last bracket right before public static void display the program skips back to line 40 if(i < right)
but suddenly the values for right, i, j and pivot have changed from to 5, 2, -1, and 3 respectively.
I would be very grateful if someone could explain why the values get changed.
I have also added two pictures which show what I see on my Eclipse window step I don't understand
public class QSort {
public static void quickSort(int[] arr, int left, int right){
int i = left;
int j = right;
int temp;
int pivot = arr[(left+right)/2];
System.out.println("\n\nleft = " + left + "\tright = " + right);
System.out.println("Pivot is: " + pivot + "(" + (left+right)/2 + ")");
while(i <= j){
while(arr[i] < pivot){
System.out.println("i is: " + arr[i] + "(" + i + ")");
i++;
System.out.println("i is: " + arr[i] + "(" + i + ")");
}
while(arr[j] > pivot){
System.out.println("j is: "+ arr[j] + "(" + j + ")");
j--;
System.out.println("j is: "+ arr[j] + "(" + j + ")");
}
if(i <= j){
System.out.println("i is: " + arr[i] + "(" + i + ")");
System.out.println("j is: "+ arr[j] + "(" + j + ")");
System.out.println("Swapped " + arr[i] + "(" + i + ")"+ " with " + arr[j] + "(" + j + ")");
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
System.out.println("i is: (" + i + ")");
System.out.println("j is: (" + j + ")");
System.out.println("Pivot is: " + pivot + "(" + (left+right)/2 + ")");
}
}
if(left < j){
System.out.println("j is: (" + j + ")");
quickSort(arr, left, j);
}
if(i < right){
System.out.println("i is: (" + i + ")");
quickSort(arr, i, right);
}
}
public static void display(int[] arr){
if(arr.length > 0){
System.out.print(arr[0]);
}
for(int i = 1; i < arr.length; i++){
System.out.print(", " + arr[i]);
}
}
public static void main(String[] args) {
int[] data = new int[]{10,5,3,22,11,2};
System.out.println("Before: ");
display(data);
quickSort(data, 0, data.length-1);
System.out.println("\nAfter: ");
display(data);
}
}
Thanks a lot!
I think your problem is that you don't fully understand recursion. At least that's what it sounds like from your desription of the question.
Anyway, I've tried to simply follow your program by keeping a trace of all variables. Hope this helps:
arr left right i j pivot
----------------- ------- -------- ------- ----- ----------
[10,5,3,22,11,2] 0 5
0 5 arr[2] = 3
[2,5,3,22,11,10] 1 4
3
2
[2,3,5,22,11,10] 2 1
The while loop has finished because i<=j is now false (2 > 1).
The first condition left < j (0 < 1) is true, so you call quicksort again recursively: quicksort(arr, 0, 1) - which means you now sort the array [2,3] which is already sorted, so nothing will happen:
arr left right i j pivot
----------------- ------- -------- ------- ----- ----------
[2,3,5,22,11,10] 0 1
0 1 arr[0] = 2
0
[2,3,5,22,11,10] 1 -1
The while loop condition is now false. The first condition left < j is false as well (because 0 > -1) and the second condition i < right is also false (because 1 == 1) So this call is finished and you return to where you were. Were was that? The first condition of the table above. The state of variables and parameters is now:
arr left right i j pivot
----------------- ------- -------- ------- ----- ----------
[10,5,3,22,11,2] 0 5 2 1 3
The second condition is checked (as it is the next line executed). Its value is also true since the condition is i < right (2 < 5). So you now do quicksort again recursively: quicksort(arr, 2, 5) - which means you now sort the array [3,22,11,10]:
arr left right i j pivot
----------------- ------- -------- ------- ----- ----------
[2,3,5,22,11,10] 2 5
2 5 arr[3] = 22
3
[2,3,5,10,11,22] 4 4
5
i > j now so we exit the while loop.
The first condition left < j (2 < 4) is true, so we call quicksort(arr, 2, 4) in order to sort [5,10,11] which is already sorted. I'll skip this part as it does not change the array at all.
When the recursive call is done, we return to where we were and now the second condition will be checked. i < right (5 < 5) is false And so we're done.
The original quicksort call has finished and the array is sorted.
The first picture you have shows the debugger is inside two recursive invocations of quicksort: quicksort is called from main, and then on line 38 calls quicksort again (this is the principle of quicksort, it's a recursive strategy). So you see you're on line 40 of the inner call, then when you step from there, you go back to the previous invocation of quicksort (the debugger shows you a stack of two lines instead of three in the top left window), and you're back to the previous values of pivot, etc. The array is passed as is to all recursive invocations so it's shared, but the integer variables aren't.
I think here it's the recursion that makes it hard to understand, check your call stack.
Your efforts of studying a sorting algorithms using print statements and a debugger are commendable! But your current implementation of Quicksort is rather difficult to understand, at least initially, because it has got both iteration and recursion going on (i.e. you use loops and at the same time, you have a procedure quicksort calling itself).
Let's take a rather different approach (purely recursive approach) to see how Quicksort works and why it works. Converting this recursive procedure to an iterative one (somewhat like you have written) is, luckily, a matter of technique (in this case)! I propose we do this here because that way we might control the complexity better. Again, the reason I am doing this is to better understand what is going on.
When Sir Tony Hoare proposed the algorithm and proved its correctness, it was something like this:
public static void qsort(int[] ints, int fi, int li) {
/* the recursive procedure */
if (fi < li) {
int p = partition(ints, fi, li); // key routine -- see below
qsort(ints, fi, p - 1);
qsort(ints, p + 1, li);
}
}
That's it! Isn't beautiful? Well, it is. All you do is:
Partition the given array. In my eyes, partitioning is an elegant procedure to solve a tricky problem well. The problem is simple: Given an array of numbers, rearrange the array such that there is a number in it, all the numbers to the left of which are smaller or equal to it and all the numbers to the right of which are larger than or equal to it -- return the index of such an element in the array. I urge you to try to solve this problem on your own. Both the procedures (Lomuto and Hoare) given on Wikipedia work well.
Once you are sure that your partitioning works as expected, you recursively sort the two partitions using the same qsort procedure (the order of recursive calls does not matter) and you are done!
I tried to implement the partition procedure myself:
/**
Implements partitioning of array a from a[p] to a[r], leaves all the other elements of the array intact.
#param a the given int array
#param p int first index of the part of array to be partitioned
#param r int the second index of the part of array to be partitioned
*/
public static int partition(int[] a, int p, int r) {
//this is something I have written
int pivot = a[p];
int i = p + 1;
int j = i - 1;
while (i <= r) {
if (a[i] < pivot) {
a[j] = a[i];
a[i] = a[j+1];
j++;
}
i++;
}
a[j] = pivot;
return j;
}
private static void swap(int[] ints, int i1, int i2) {
int tmp = ints[i2];
ints[i2] = ints[i1];
ints[i1] = tmp;
}
Now, I haven't yet proved the correctness of this procedure, but we can do that separately. You can even reimplement the Lomuto procedure and see that it works to your satisfaction.
And that's it. If you now want to debug this with a debugger, you are more than equipped to do it. Here's the entire implementation.
Now, the question of converting this recursive procedure to an iterative one is very interesting and this document: (shameless plug: I wrote it) http://bit.ly/recurse-iterate should give you some clues. Actual conversion of the above Quicksort procedure to an iterative one is left as an exercise to the reader :-).

Categories

Resources