Nested loops are fine as long as they describe the correct algorithm.
Nested loops have performance considerations (see @Travis-Pesetto's answer), but sometimes it's exactly the correct algorithm, e.g. when you need to access every value in a matrix.
Labeling loops in Java allows to prematurely break out of several nested loops when other ways to do this would be cumbersome. E.g. some game might have a piece of code like this:
Player chosen_one = null;
...
outer: // this is a label
for (Player player : party.getPlayers()) {
for (Cell cell : player.getVisibleMapCells()) {
for (Item artefact : cell.getItemsOnTheFloor())
if (artefact == HOLY_GRAIL) {
chosen_one = player;
break outer; // everyone stop looking, we found it
}
}
}
While code like the example above may sometimes be the optimal way to express a certain algorithm, it is usually better to break this code into smaller functions, and probably use return instead of break. So a break with a label is a faint code smell; pay extra attention when you see it.
Videos
Nested loops are fine as long as they describe the correct algorithm.
Nested loops have performance considerations (see @Travis-Pesetto's answer), but sometimes it's exactly the correct algorithm, e.g. when you need to access every value in a matrix.
Labeling loops in Java allows to prematurely break out of several nested loops when other ways to do this would be cumbersome. E.g. some game might have a piece of code like this:
Player chosen_one = null;
...
outer: // this is a label
for (Player player : party.getPlayers()) {
for (Cell cell : player.getVisibleMapCells()) {
for (Item artefact : cell.getItemsOnTheFloor())
if (artefact == HOLY_GRAIL) {
chosen_one = player;
break outer; // everyone stop looking, we found it
}
}
}
While code like the example above may sometimes be the optimal way to express a certain algorithm, it is usually better to break this code into smaller functions, and probably use return instead of break. So a break with a label is a faint code smell; pay extra attention when you see it.
Nested loops are frequently (but not always) bad practice, because they're frequently (but not always) overkill for what you're trying to do. In many cases, there's a much faster and less wasteful way to accomplish the goal you're trying to achieve.
For example, if you have 100 items in list A, and 100 items in list B, and you know that for each item in list A there's one item in list B that matches it, (with the definition of "match" left deliberately obscure here), and you want to produce a list of pairs, the simple way to do it is like this:
for each item X in list A:
for each item Y in list B:
if X matches Y then
add (X, Y) to results
break
With 100 items in each list, this will take an average of 100 * 100 / 2 (5,000) matches operations. With more items, or if the 1:1 correlation is not assured, it becomes even more expensive.
On the other hand, there's a much faster way to perform an operation like this:
sort list A
sort list B (according to the same sort order)
I = 0
J = 0
repeat
X = A[I]
Y = B[J]
if X matches Y then
add (X, Y) to results
increment I
increment J
else if X < Y then
increment I
else increment J
until either index reaches the end of its list
If you do it this way, instead of the number of matches operations being based on length(A) * length(B), it's now based on length(A) + length(B), which means your code will run much faster.
Looks like you are only worried about the count. So, if modifying an array is not an issue then, apply quick sort in O(nlog(n)) and then count the neighbours in O(n).
You can use a HashSet which has O(1) complexity of contains method - because hashCode of Integer value in Java is well distributed (it's just a value of the Integer) you should have constant complexity always
HashSet<Integer> set = new HashSet();
for (int i=0; i<n; i++) {
if(set.contains(arr[i])) {
total++;
} else {
set.add(arr[i]);
}
}
Read more here:
- HashSet look-up complexity?
There's also one additional algorithm that could be implemented here but it require some data limitations (due to the max length of array on your machine).
You could just create an int array yourarray initialized with 0 with a length of max(arr) + 1. Then you are iterating over arr every time executing yourarray[arr[i]]++ and then you are iterating over yourarray checking where the value is greater than 1 - if it this then it means that this value has to repeat