Reputation: 61
This method's duty is to remove all occurrences of the value toRemove
from the arrayList. The remaining elements should just be shifted toward the beginning of the list (the size will not change). All "extra" elements at the end (however many occurrences of toRemove
were in the list) should just be filled with 0. The method has no return value, and if the list has no elements it should just have no effect. Cannot use remove()
and removeAll()
from the ArrayList class.
The method signature is:
public static void removeAll(ArrayList<Integer> list, int toRemove);
The solution:
public static void removeAll(ArrayList<Integer> list, int toRemove) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) = toRemove) {
for (int j = i + 1; j < list.size(); j++) {
list.set(j - 1, list.get(j));
}
list.set(list.size() - 1, 0);
i--;
}
}
I understand the first for
loop and the if
statement well. Because one would want to iterate through the entire arrayList one-by-one and for each index with a number present in the arrayList check if it is, in fact the toRemovee
integer. After this point I become lost.
Why another for
loop? Why do we start the second for
-loop one after where the last one was?
Why within that second for
loop do we use list.set()
, I understand that set
method takes in two arguments, the index position and the element to sub into that designated position. Why j-1
? Why after this second loop is over is there the line: list.set(list.size()-1, 0)
? Why the i--
?
There are a lot of moving parts and I would like to understand the logic.
Thank you
Upvotes: 2
Views: 996
Reputation: 875
If you want to do the same in an FP style; return a new List instead of modifying the input, you can do this with Streams.
public static List<Integer> removeAll(ArrayList<Integer> list, int toRemove) {
Integer rem = new Integer(toRemove); // OR change toRemove to Integer
List<Integer> ret = list.stream()
.filter(i -> !(i.equals(rem)))
.collect(Collectors.toList());
return ret;
//if you NEED to return ArrayList instead of List
//return new ArrayList<>(ret);
}
Upvotes: 0
Reputation: 17534
Why do we start the second for-loop one after where the last one was?
Each time an occurence is found, we want to left shift by 1 all following values of the arraylist.
Why within that second for loop do we use list.set(), I understand that set method takes in two arguments, the index position, and the element to sub into that designated position. Why j - 1?
j-1
is used to shift left by 1 .
Why after this second loop is over is there the line: list.set(list. sise () - 1, 0) ?
We shifted values left, but the value at the last index (size-1) has not been replaced by anything, we want it to be 0
.
why the i--?
As the value at the current index has been overwritten by another value, we want to start next iteration at the same index (i--
compensating i++
).
Upvotes: 0
Reputation: 14917
Why another
for
-loop? Why do we start the secondfor
-loop one after where the last one was? Why within that second for loop do we uselist.set()
, I understand that set method takes in two arguments, the index position, and the element to sub into that designated position. Whyj - 1
?
The method does everything the documentation says. The inner loop shifts the elements left by one.
for (int j = i + 1; j < list.size(); j++) {
list.set(j - 1, //The index before j (that is, j - 1) is set to...
list.get(j)); //the current element.
}
}
Starting at the element after the found index, it sets the one to the left to the current element. Eventually, you'll end up with all elements having been shifted left.
list.set(list.size() - 1, 0);
This sets the last element to zero. Since your list has had one element removed, you need to get rid of the last one because everything has been shifted.
Example:
In these examples, ^
is i and *
is j
.
0 1 2 3 4
Say I want to remove 2.
First, I'll loop until I find 2.
0 1 2 3 4
^ index: 2
Now, I'll shift everything left to remove that element. Because we're shifting left, we need to start at i + 1
(hence the for
-loop starting at i + 1
.
0 1 3 3 4
^ * (replaced the one before *)
Next, we do it again.
0 1 3 4 4
^ *
Now we're done.
list.set(list.size() - 1, 0);
However, 4 is left at the end. We need to remove that because we removed an element, and the list is one element shorter. So, we set the last element to zero to remove it (of course, this assumes zero is not a valid value in the list).
Note:
I would strongly suggest doing list.remove(list.size() - 1)
instead of the call to set
. This actually removes the last item and does not leave it with a "magic number" default value.
Why the
i--
?
You need i--
because everything has been shifted left, so you'll need to update the index 1 to the left, namely by subtracting one. (Actually, what you need to do is start the iteration at the same index, but since the for
-loop executes i++
every iteration you need to do i--
to "cancel" it out.)
Upvotes: 4