Understanding this remove method solution with arrayList [duplicate] - java

This question already has answers here:
Understanding this removeAll java method with arrayList
(3 answers)
Closed 6 years ago.
This methods 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 are we taking the previous loops variable and adding 1 to it?
why within this second loop are we using the parameters "list" and using a set method?
why j - 1?
why list.get(j)?
Why after this second loop is over is there the line:
list.set(list. sise () - 1, 0) ?
why the i--?
There are a lot of moving parts and I would like to understand the logic.
Thank you

Firstly the if statement is assignment operation which isn't correct. You need to change the = to ==. I have explained each step in the code -
public static void removeAll(ArrayList<Integer> list, int toRemove) {
//start with the first number in the list until the end searching for toRemove's
for (int i = 0; i < list.size(); i++) {
//if the value at i is the one we want to remove then we want to shift
if (list.get(i) == toRemove) {
//start at the index to the right until the end
//for every element we want to shift it the element to its left (i == j - 1)
for (int j = i + 1; j < list.size(); j++) {
//change every value to whatever was to the right of it
//this will overwrite all values starting at the index where we found toRemove
list.set(j - 1, list.get(j));
}
//now that everything is shifted to the left, set the last element to a 0
list.set(list.size() - 1, 0);
//decrement to adjust for the newly shifted elements
// this accounts for the case where we have two toRemoves in a row
i--;
}
}
}
By the end of this function any value that matches toRemove is "removed" by shifting the arraylist to the left everytime the value is found and the last element will be set to 0.
Example
removeAll([1,2,3,4,5,5,6,7,8,5,9,5], 5)
Output
[1,2,3,4,6,7,8,5,9,0,0,0]

Please see the following to learn details (from minute 5:50 or 5:57)
https://www.youtube.com/watch?v=qTdRJLmnhQM
You need the second for loop ,to take all elements after the element you’ve removed it and shift it over one to the left so basically it’s filling up the space that is left empty from removing it so this is what this is doing.

Related

Removing duplicates from a sorted array IN-PLACE without allocating space for a second array

I'm tasked with a perplexing problem. I'm attempting to turn an unsorted array with duplicates into a sorted array without duplicates. I used the selection sort to accomplish the first part:
public static void SelectionSort(int [] list) {
int i = 0;
int j = 0;
int indexSmallest = 0;
int temp = 0;
for (i = 0; i < list.length - 1; i++) {
indexSmallest = i;
for (j = i + 1; j < list.length; j++) {
if (list[j] < list[indexSmallest]) {
indexSmallest = j;
}
}
temp = list[i];
list[i] = list[indexSmallest];
list[indexSmallest] = temp;
}
}
The sorting isn't the issue - I'm having a hard time removing the duplicates from the array. The solution that I have in my head is to create a secondary array, and iterate through the input to check if that element exists in the second array, if not, add it to the array. I'm stuck because I'm not able to create another array. So, what gives? How do I solve this problem if I can't create an array to cross-reference and check if I have unique values? I'm not able to use any built-in Java functions.
There is no need of second array ... think about it this way ...
The easiest way is to convert it to set / hashset and then sort it in an array.
But if the sets are forbidden, the only possibility is to put the duplicates at the end, cut them out and then sort the rest.
[1,8,1,2,3,5,3] in this array, you need to remove elements that are duplicates ... okay ... so what if we did something like this ... we will "split" this array into "sorted", "unsorted and duplicates" and "duplicates". Now what we will do is that we will go through the array using 2 pointers. One at the first element (lets call it "i") and at the last element (lets call it "j") ... now we will go while i < j and we will swap everytime, when we will find a duplicate. This way, you will get everything not duplicate before "i" and everything that is dupicate after "i" ... now you will sort the array from index 0 do index i and you should have sorted array and you will just cut out the duplicates ...
ofc., this will require the time complexity, to be able to handle O(n*logn) / O(n^2) ...
There is a way how to do it in a O(n), and that can be done by that .. you will use 2 pointers ...
one will be pointing at current sorted array, where you have no duplicates and toher will be pointing to a place, where are yet unswapped integers ... (you need to remember the highest number found)
to be more specific:
[1,2,2,3,3,4,5]
i = 0, j = 1
- fine
i = 1, j = 2
- duplicate ... soo ..
jumping to duplicate position
i = 2, j = 3 (array[3] != 2, so we will swap)
current array -> [1,2,3,2,3,4,5]
^ ^
i j
i = 3, j = 4
- highest_number > 3 is not true (2 < 3), so skipping
i = 3, j = 5
- highest_number > 3 is not true (3 < 3), so skipping
i = 3, j = 6
- swapping
... etc
and you should end up with something like this
[1,2,3,4,5,2,3]
^ ^
i j
now you can cut the array at i, so you will get `[1,2,3,4,5,\0]` (in C syntax) ... so basically `[1,2,3,4,5]`

how to iterate over consecutive pairs in arrayList

I want to create a loop that iterates through an ArrayList of objects.
for (int i = 0, k=i+1; k < arr.size(); i++) {
int tprice;
tprice=0;
if (arr.get(i).getID()=arr.get(i+1).getID()) {
tprice = arr.get(i).getPrice() + arr.get(i+1).getPrice();
}
else {
if (tprice!=0) {
System.out.println(tprice);
}
else {
System.out.println(arr.get(i).getDuration());
}
}
}
I want to compare element i to element i+1 of the ArrayList, without creating a nested for loop as I am not interested in all the permutations. (e.g, 1->2 then 2->3, not 1->2 then 1->3)
However, my line of code always causes an error because index k at the end of the loop is referencing an out-of-bounds index (or the equivalent for ArrayList).
Say i have three arrays : i=0 compares to i=1, i=1 compares to i=2, i=2 compares to i=3 but throws back an error since it doesn't exist.
Is there any way to overcome this? It seems silly, but I couldn't find anything about it across the forums.
exemple hardcode:
arr.add(new object(444,24)) // 444 is ID, 24 is Price
arr.add(new object(444,29)) // 444 is ID, 29 is Price
arr.add(new object(121,33)) // ...
wanted outcome :
53
53
33
side-question : if i am dealing with the same ID, i would ideally wish to print only once. Is there anyway to do so?
If you touch the two consequent elements of the array, you have to stop one element before you read the end:
for (int i = 0; i < arrayList.size() - 1; i++) {
// do stuff with arrayList.get(i) and arrayList(i+1)
}
Of course, the arrayList must contain at least two elements otherwise the loop will never be entered since the arrayList.size() - 1 would be equal to 0.
Moreover, you confuse arrays with ArrayList<T>.
List<T> of size list.size() has methods list.add(T t) and list.get(int index).
An array int[] array of size (length) array.length access to items with index array[0].
If all you want to check is the adjacent elements in the array, just start from the index 1 till the end and compare the adjacent: current and previous.
for (int i = 1; i < arr.size(); ++i) {
if (arr.get(i) > arr.get(i-1)) ....
}

Nested For Loops for Array Item Removal

This is probably a noobish question but, i have been working on this project and couldn't get it to work. I got frustrated and experimented around and got it to work somehow. The change i made was i added a -1 to numOfItem.
I would really appreciate if someone could explain to me why this worked. My head is not really reading the code properly i believe. I am under the impression that if i am removing an item on the last index, it should throw an error.
for (int j = i; j < numOfItem - 1; j++)
This code belongs to a nested for loop in this method:
//Removes only a single instance of the specified item.
//If the item doesnt exist in the bag, it returns false
public boolean remove(Object item) {
for (int i = 0; i < numOfItem; i++) {
if (stuff[i].equals(item)) {
for (int j = i; j < numOfItem - 1; j++)
stuff[j] = stuff[j + 1];
stuff[numOfItem - 1] = null;
numOfItem--;
return true;
}
}
return false;
}
numOfItem is set to 0, when an object bag is initialized, as to signify there are 0 items in the bag, however the bag is given a max capacity (user input) when initialized. If any more info is needed, please let me know. Thanks in advance.
Your code it trying to remove an element from an array if it is found using the following steps:
Step 1 :
Find the element.
Step 2 :
a) If not found, return false;
b) If found, shift all the elements to the left from the index where the element is found.
c) Set the last index of array as null.
In the Step 2 b) shift is done by:
for(int j = i; j < numOfItem - 1; j++)
stuff[j] = stuff[j + 1];
In this above code, you need to iterate for loop till second last index only, because the last index needs to be set as null to decrement the array size after deleting the element. If you try to iterate on last index, then stuff[j+1] will throw ArrayIndexOutOfBoundException. Thats why numOfItem -1 works.
I am assuming you are referring to the line stuff[numOfItem - 1] = null If this is the case then the answer is simple. Array indexing starts at 0, not 1 therefore if you have 50 items in your array (numOfItem = 50) then the indexing will be 0, 1, 2, 3...49 There is not 50th value as index 0 is technically the 1st value in the array. Therefore if you wrote stuff[numOfItem] = null you would be trying to access the 50th index in the array however, the largest index in the array is 49 since it starts at 0, not 1.

Understanding the logic of this method to find the position of the largest element in the array

The purpose of this method is to return the position (subscript index) of the largest element in the array (not its value, but its position). If the same maximum value appears more than once in the array, then it should return the position of the first or earliest on. If the array has no elements it should just return -1.
The solution:
public static int maxPos(int[] arr) {
int pos = 0;
if(arr.length > 0 ) {
for(int i = 0; i < arr.length; i++) {
if(arr[i] > arr[pos]) {
pos = i;
} else {
pos = - 1;
}
}
return pos;
}
I understand setting up a dummy variable "pos" to represent the index position of the maximum value of the array. And having the check point with if(arr.length > 0) then proceed. And the for-loop to sift through the entire array checking one-by-one which index has the greatest number value and after each iteration either re-assigning dummy variable or carrying onward.
The part where I get lost is when using things within the array [ ]'s, it throws me off. I don't think anywhere else in java there is such notation. For example with arrayList wouldn't that just be nameOfAL . get();
So the equivalent of that for an array is using the []'s?
I am a bit confused by arr[i] > arr[pos].
Is this to say when we are at the i'th index in the for-loop, we can then use arr[] and put something within that box, and when we do it outputs the value of that index. So anytime we put something within that array box it's always going to output an index position? is that the purpose of putting things inside the [] box? it will output the value of whatever is put inside it's brackets.
the next part that confuses me is why pos = i?
I understand if the if-statement fails then the else is - 1. but why return pos; after each iteration?
Thank you
Your posted code contains a few bugs, you should start with pos at -1 (instead of resetting it when a given value isn't greater then the current max). Also, I would check for null. Then you can start your loop with the second element. Something like,
public static int maxPos(int[] arr) {
int pos = -1; // <-- indicates no elements.
if (arr != null && arr.length > 0) {
pos = 0; // <-- there is at least one element.
for (int i = 1; i < arr.length; i++) {
if (arr[i] > arr[pos]) {
pos = i; // <-- update the max position
}
}
}
return pos;
}
First, so what you're putting in the square braces are variables named i and pos that hold the values of the numerical positions you're accessing in the array. It's like the get method of the arrayList class like that.
It's not returning pos until it finishes the for loop. In general it's returning pos because that's the index of the largest number, which is the point of the program. I think you're just missing a bracket somewhere, you have 5 {'s and 4 }'s.

How to shift element in an Arraylist to the right in java

So I am trying to create a method that shifts all of the elements in an arraylist to the right and the last element will become the first element. When I run the code, I am told I have an out of bounds error. Here is what I have so far:
public void shiftRight()
{
//make temp variable to hold last element
int temp = listValues.get(listValues.size()-1);
//make a loop to run through the array list
for(int i = listValues.size()-1; i >= 0; i--)
{
//set the last element to the value of the 2nd to last element
listValues.set(listValues.get(i),listValues.get(i-1));
//set the first element to be the last element
listValues.set(0, temp);
}
}
Maybe this is an exercise you are working on, but the ArrayList.add(int index,E element) method does almost what you want.
"Inserts the specified element at the specified position in this list. Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices)." (italics added)
So just add the last element in the list at position 0. And delete it from the end.
A few problems here:
Your for loop condition needs to exclude the zeroth element so it should be i > 0 otherwise you'll get to the point where you want to put element at position -1 to position 0 resulting in out of bounds error.
Setting the first element to be the last should be outside the loop.
listValues.set takes in an index in the list as the first parameter, you are giving it the object in the list
public void shiftRight()
{
//make temp variable to hold last element
int temp = listValues.get(listValues.size()-1);
//make a loop to run through the array list
for(int i = listValues.size()-1; i > 0; i--)
{
//set the last element to the value of the 2nd to last element
listValues.set(i,listValues.get(i-1));
}
//set the first element to be the last element
listValues.set(0, temp);
}
The easiest and shortest solution : (if you don't have concurrent use of list - Because in concurrent use and iterating on it, the list size should not change, otherwise you get ConcurrentModificationException)
public void shiftOneToRight() {
listValues.add(0, listValues.remove(listValues.size() - 1));
}
Here is the simplest solution
Collections.rotate(list, rotationPosition);
my code to put a number in the right place in a List
int nr = 5; // just a test number
boolean foundPlace = false;
for(int i = 0; i < integerList.size(); i++){
if(nr <= integerList.get(i)){
integerList.add(i,nr);
foundPlace = true;
break;
}
}
if (!foundPlace)
integerList.add(integerList.size(), nr);
as the guy above said, "integerList.add(element)" inserts the specified element at the specified position in this list. Shifts the element currently...
input array list: locationMap
shift LHS elements from idxStart in circular way
shifted output list: extendedList
// make extended list to behave like circular
List<String> extendedList = new ArrayList<>();
for (int i = idxStart; i < locationMap.size(); i++) { // current to end
extendedList.add(locationMap.get(i));
}
for (int i = 0; i < idxStart; i++) { // 0 to current
extendedList.add(locationMap.get(i));
}

Categories

Resources