Java while loop mysterious iteration - java

Can somebody teach me how the while loop in find method is working? Does that somehow iterates the parent array from 0 to the endpoint automatically? until paren[i] != i?
static int find(int i)
{
while (parent[i] != i)
i = parent[i];
return i;
}
// Finds MST using Kruskal's algorithm
static void kruskalMST(int cost[][])
{
int mincost = 0; // Cost of min MST.
// Initialize sets of disjoint sets.
for (int i = 0; i < V; i++)
parent[i] = i;
// Include minimum weight edges one by one
int edge_count = 0;
while (edge_count < V - 1)
{
int min = INF, a = -1, b = -1;
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (find(i) != find(j) && cost[i][j] != 0 && cost[i][j] < min)
{
min = cost[i][j];
a = i;
b = j;
}
}
}

It's difficult to see what you're not grasping - it executes as written.
find is called with some value of i
Does the i'th entry in the parent array contain the value i? Yes, then control proceeds to the return statement and we're done.
Otherwise, set the value in i to the value from the i'th entry of the 'parent' array.
Does the i'th entry in the parent array contain the value i?
Yes, then control proceeds to the return statement and we're done.
Otherwise, set the value in i to the value from the i'th entry of the 'parent' array.
… and keep doing this ...
The overall logic seems to be that each entry in the parent array is supposed to identify its parent entry, except that the topmost entry has itself for its parent.
However, since all entries in parent are initialized such that the i'th entry contains i, and nothing changes that, it seems the code shown is incomplete.

Related

I am trying to loop through an ArrayList to find the lowest value of a sensor reading

My instructions are: Create a sensor object that refers to element zero. Write a for loop that starts at element 1, loops through all the elements of the arraylist and check to see if the value of the sensor reading is smaller than element zero. I am supposed to assume that element zero has the minimum value already. If the value is smaller, set that as the minimum value. Here is the code I have, but it is not finding the minimum value.
public int findMinReadingIndex() {
ArrayList<SensorReading> sensorReadings = new ArrayList<>();
sensorReadings.get(0);
int minIndex = 0;
for(int i=1; i< sensorReadings.size(); i++) {
if (this.sensorReadings.get(i).getValue() < i)
minIndex = i;
}
return minIndex;
}
It is better to focus on the problem: you have a list, and you want to find an index with minimum value. So you have to write method that accepts List<SensorReading> and retrieves int value. Note, that using get() is not optimal, especially if you do not know concrete implementation of the List. You have to use iterator instead.
public int findMinReadingIndex(List<SensorReading> sensorReadings) {
int minIndex = 0;
int minValue = 0;
int i = 0;
for(SensorReading sensorReading : sensorReadings) {
if(i == 0 || sensorReading.getValue() < minValue) {
minValue = sensorReading.getValue();
minIndex = i;
}
i++;
}
return minIndex;
}
Minor change is below:
public int findMinReadingIndex() {
ArrayList<SensorReading> sensorReadings = new ArrayList<>();
float minReading = sensorReadings.get(0).getValue();
int minIndex = 0;
for(int index = 1; index < sensorReadings.size(); index ++) {
float reading = this.sensorReadings.get(index).getValue();
if (reading < minReading)
minIndex = index;
}
return minIndex;
}
If you using Java 8 one liner code use stream with Comparator API.
SensorReading minVal = sensorReadingList.stream().min(Comparator.comparing(SensorReading::getValue))
.orElseThrow(NoSuchElementException::new);
System.out.println(minVal.getValue());
First of all calling stream() method on the list to get a stream of
values from the list.
After that call to min() method on the stream to get the minimum
value from the list.
We are passing a lambda function as a comparator, sort the list and
deciding the minimum value.
After that we call orElseThrow() to throw an exception if no value
is received from min()

Need help understanding segment of code

public int[] selectionSort(int array[]) {
for(int i = array.length - 1; i >= 0; i--) {
int highestIndex = i;
for(int j = i; j >= 0; j--) {
if(array[j] > array[highestIndex])
highestIndex = j;
}
int temp = array[i];
array[i] = array[highestIndex];
array[highestIndex] = temp;
}
return array;
}
I understand the concept of selection sort, but the code is confusing me. Specifically, can someone explain what is happening in the last three statements of the outer for-loop starting with "int temp = array[i];"
This is the famous swapping routine. In languages like Java, when you want to swap the values of two variables named say a and b, you have to resort to such a routine where you use a third variable to hold a value in transit:
int a = 2;
int b = 6;
int tmp = a; // now tmp has a value that is _copy_ of a i.e. 2
a = b; // since we saved a in tmp, we can _mutate_ it, now a has b's value
b = tmp; // swap! here, b = a won't work because a contains b's current value.
// now a has value 6 and b has value 2, exactly what we wanted.
In some other languages, a construct like a, b = b, a is available for this purpose, which is more intuitive in my opinion.
In selection sort, after the inner loop has found the index of the element that holds the highest value, you need to swap it with the element held by the outer loop index and that's what this achieves in that context.

Gets the number of duplicates in the list - wrong output

How to count duplicates in ArrayList and count only once.
Here is what I have so far:
/**
* Gets the number of duplicates in the list.
* Get the next word. It is at index i. Does it match any of the words with index > i?)
* #return the number of duplicate words in the list
*/
public int countDuplicates() {
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i; j < list.size(); j++) {
if (list.get(i).equals(j)) duplicates++;
}
}
return duplicates;
}
Here is check output:
Actual: 0
Expected: 3
I am missing something very easy. However, couldn't find what exactly it is.
How to solve this trouble?
You don't get the jth element you just compare to j directly. And as a commenter points out, j should start at i+1 to avoid comparing an element to itself. Therefore, you need to write
public int countDuplicates()
{
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Should be:
public int countDuplicates()
{
int duplicates = 0;
// TODO: Write the code to get the number of duplicates in the list
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Use two sets for this:
final Set<X> set = new HashSet<>();
final Set<X> dups = new HashSet<>();
int dupCount = 0;
for (final X x: list) {
if (set.add(x)) // first time the element is seen
continue;
// Dup; see whether it is the first time we see it
if (dups.add(x))
dupCount++;
}
return dupCount;
This relies on the fact that Set's .add() returns true if and only if the set has been modified as the result of the operation. And note that it traverses the list only once.
I can see three problems with your current code:
You are not comparing pairs of elements. You are actually comparing an element with an index.
Your inner loop is comparing element i and element i ... and that would result in a false "duplicate" count.
If you have more than 2 copies of any given element, then you will get too many duplicate counts. (To see why, try to "hand execute" with a list of (say) three identical elements.
In fact, you have to EITHER use an auxiliary data structure (e.g. 2 Sets or a Map) OR modify the input list to avoid counting duplicates more than once.
I would note that your statement of the problem is ambiguous. "... only count each duplicate once" could mean that '[1, 1, 1]' gives either 1 or 2. It depends whether you consider each individual 1 to be a duplicate to be counted once or that we have 1 as one of a set of duplicates ... that must only be counted once.
You are comparing index j value instead of value of list list.get(j).
Do
if (list.get(i).equals(list.get(j)))
instead of
if (list.get(i).equals(j))

Rearranging array when it has a null position

I have this code that searches one object in an array and removes it. I'm having a problem with its position, since some other methods work with this array (and it gives me a NullPointerException every time). My method looks like this:
public void deleteHotel(String hotelName) {
for (int i = 0; i < this.hoteis.length; i++) {
if (this.hoteis[i].getName().equalsIgnoreCase(nomeHotel)) { //searches the array, looking for the object that has the inputted name
this.hoteis[i] = null; //makes that object null
if (this.hoteis.length > 1 && this.hoteis[this.hoteis.length - 1] != null) { //for arrays with lenghts bigger than 1 (since there's no problem with an array with one position)
for (int x = i; x < this.hoteis.length; x++) {
this.hoteis[x] = this.hoteis[x + 1]; //makes that null position point to the next position that has an object, and then that position points to the object in the next position and so on
}
this.hoteis[this.hoteis.length - 1] = null; //since the last to positions will be the same, make that last one null
Hotel[] hoteisTemp = new Hotel[this.hoteis.length - 1];
for(int x = 0; x < this.hoteis.length - 1; x++){ //create a new array with one less position, and then copy the objects on the old array into the new array, then point the old array to the new array
hoteisTemp[x] = this.hoteis[x];
}
this.hoteis = hoteisTemp;
}
i = this.hoteis.length;
}
}
}
When I use other methods (for example, one that returns the implemented toString()s of each object) it gives me a NullPointerException. Can you guys identify the error in the code? Much appreciated...
I have tested your function and I see what you mean by it getting a nullpointerexception, this is due to the array not resizing the list - which is due to your conditional:
if (this.hoteis.length > 1 && this.hoteis[this.hoteis.length - 1] != null).
Simply removing this solved the issue, here is the working function:
public static void deleteHotel(String hotelName) {
for (int i = 0; i < hotels.length; i++) {
if (hotels[i].getName().equalsIgnoreCase(hotelName)) { //searches the array, looking for the object that has the inputted name
hotels[i] = null; //makes that object null
for (int x = i; x < hotels.length -1; x++)
hotels[x] = hotels[x + 1]; //makes that null position point to the next position that has an object, and then that position points to the object in the next position and so on
Hotel[] hoteisTemp = new Hotel[hotels.length - 1];
for(int x = 0; x < hotels.length - 1; x++) //create a new array with one less position, and then copy the objects on the old array into the new array, then point the old array to the new array
hoteisTemp[x] = hotels[x];
hotels = hoteisTemp;
break;
}
}
}
Though please consider using a list of some sort when needing to use a list with a changing size.
The fundamental problem is that you're not allowing for where you removed the entry from the array.
Instead of
for(int x = 0; x < this.hoteis.length - 1; x++){
you want
for(int x = 0; x < this.hoteisTemp.length; x++){
(although that's a style choice)
and more significantly, instead of
hoteisTemp[x] = this.hoteis[x];
you want
int y = x < i ? x : x + 1;
hoteisTemp[x] = this.hoteis[y];
You also want to get rid of everywhere you're setting array elements to null, because if your copying logic works correctly, that's unnecessary.
For this use case, I would consider using one of the List implementations.
Consider rewriting your code
List result = new ArrayList();
for (int i = 0; i < this.hoteis.length; i++) {
if (!this.hoteis[i].getName().equalsIgnoreCase(nomeHotel)) {
result.add(this.hoteis[i]);
}
}
return result.toArray();
The point where you're shifting the array elements towards the left
for (int x = i; x < this.hoteis.length; x++) {
this.hoteis[x] = this.hoteis[x + 1];
}
The loop condition should be x < this.hoteis.length - 1 because at the last iteration when x = this.hoteis.length - 1 the index value this.hoteis[x + 1] would throw a NullPointerException.
Try using ArrayList it will simplify your code complexity.Here is the link to documentation.
http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html

Count The Amount Of Data In An Array Including SOME Null

I'm coding in java and I need to create a function that returns the number of data objects that are currently in an ArrayList. At the moment I have this:
int count = 0;
for (int i = 0; i < data.length; i++)
{
if (data[i] != null)
{
count ++;
}
}
return count;
But the problem is that an array list that includes null data is acceptable, and I have to count their null data towards this counter. How do I include the null data that's in the middle of this array, and not the null data that's not supposed to be counted for?
For example, I have some tester code that adds (8),null,null,(23),(25) to the array, and this function should return 5 when the initial array size is 10.
I'm going to assume you're using a regular array (your question is somewhat ambiguous about this). Traverse through the array backwards until you find a non-null element:
public static int count(Object[] a) {
int i = a.length - 1;
for (; i >= 0 ; i--)
if (a[i] != null)
break;
return i + 1;
}
You could also have
public static <T> int count(T[] a) {
int i = a.length - 1;
for (; i >= 0 ; i--)
if (a[i] != null)
break;
return i + 1;
}
Let's test it out, using an example analogous to the one you provided:
Object[] a = new Object[10];
a[0] = new Object();
a[3] = new Object();
a[4] = new Object();
System.out.println(count(a));
Output:
5
You will need two separate counters. The first one will count normally. The second one starts counting when you find null data. Then when you find a non-null data, just add the second counter to the first one and continue counting with the first counter until you find a null again.
int count = 0;
for (int i = data.length - 1; i >= 0; i--)
if (data[i] != null || count > 0)
count += 1;
return count;
At least that's how I understood your requirements - count nulls, except for trailing nulls.
But maybe that's not actually what you meant?
Edit
Unless you're actually using ArrayList (as Jon was asking), where .size() is different from capacity and will count all added elements (including nulls). You can't actually even get the capacity from an ArrayList.

Categories