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)) ....
}
Related
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]`
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.
I wrote below code to get duplicate elements from Arraylist. My aerospikePIDs list doesn't have any duplicate value but still when I am executing below code it is reading if condition.
ArrayList<Integer> aerospikePIDs = new ArrayList<Integer>();
ArrayList<Integer> duplicates = new ArrayList<Integer>();
boolean flag;
for(int j=0;j<aerospikePIDs.size();j++) {
for(int k=1;k<aerospikePIDs.size();k++) {
if(aerospikePIDs.get(j)==aerospikePIDs.get(k)) {
duplicates.add(aerospikePIDs.get(k));
flag=true;
}
if(flag=true)
System.out.println("duplicate elements for term " +searchTerm+duplicates);
}
}
Your inner loop should start from j + 1 (not from 1), otherwise when j = 1 (second iteration of j), for k = 1 (first iteration of k for j value equals to 1).
aerospikePIDs.get(j)==aerospikePIDs.get(k)
returns true.
So the code should be:
ArrayList<Integer> aerospikePIDs = new ArrayList<Integer>();
ArrayList<Integer> duplicates = new ArrayList<Integer>();
for (int j = 0; j < aerospikePIDs.size(); j++) {
for (int k = j + 1; k < aerospikePIDs.size(); k++) {
if (aerospikePIDs.get(j)==aerospikePIDs.get(k)) {
duplicates.add(aerospikePIDs.get(k));
System.out.println("duplicate elements for term " +searchTerm+duplicates);
}
}
}
Note: the flag is not necessary, because if you addeda duplicate you can print it directly in the if, without defining new unnecessary variables and code.
Use higher level abstractions:
Push all list elements into a Map<Integer, Integer> - key is the entry in your PIDs list, value is a counter. The corresponding loop simply checks "key present? yes - increase counter; else, add key with counter 1".
In the end, you can iterate that map, and each entry that has a counter > 1 ... has duplicates in your list; and you even get the number of duplicates for free.
And questions/answers that show you nice ways to do such things ... are posted here on almost daily basis. You can start here for example; and you only need to adapt from "String" key to "Integer" key.
Really: when working with collections, your first step is always: find the most highlevel way of getting things done - instead of sitting down and writing such error-prone low-level code as you just did.
You are iterating using the same arraylist. You are checking every data in inner for loop, for sure it will display duplicates.
I have a string array
"Ben", "Jim", "Ken"
how can I print the above array 3 times to look like this:
"Ben", "Jim", "Ken"
"Jim", "Ben", "Ken"
"Ken", "Jim", "Ben"
I just want each item in the initial array to appear as the first element. The order the other items appear does not matter.
more examples
Input
"a","b","c","d"
output
"a","b","c","d"
"b","a","c","d"
"c","b","a","d"
"d","a","c","d"
Method signature
public void printArray(String[] s){
}
Rather than give you straight-up code, I'm going to try and explain the theory/mathematics for this problem.
The two easiest ways I can come up with to solve this problem is to either
Cycle through all the elements
Pick an element and list the rest
The first method would require you to iterate through the indices and then iterate through all the elements in the array and loop back to the beginning when necessary, terminating when you return to the original element.
The second method would require you to iterate through the indices, print original element, then proceed to iterate through the array from the beginning, skipping the original element.
As you can see, both these methods require two loops (as you are iterating through the array twice)
In pseudo code, the first method could be written as:
for (i = array_start; i < array_end; i++) {
print array_element[i]
for (j = i + 1; j != i; j++) {
if (j is_larger_than array_end) {
set j equal to array_start
}
print array_element[j]
}
}
In pseudo code, the second method could be written as:
for (i = array_start; i < array_end; i++) {
print array_element[i]
for (j = array_start; j < array_end; j++) {
if (j is_not_equal_to i) {
print array_element[j]
}
}
}
public void printArray(String[] s){
for (int i = 0; i < s.length; i++) {
System.out.print("\"" + s[i] + "\",");
for (int j = 0; j < s.length; j++) {
if (j != i) {
System.out.print("\"" + s[j] + "\",");
}
}
System.out.println();
}
}
This sounds like a homework question so while I feel I shouldn't answer it, I'll give a simple hint. You are looking for an algorithm which will give all permutations (combinations) of the "for loop index" of the elements not the elements themselves. so if you have three elements a,b,c them the index is 0,1,2 and all we need is a way to generate permutations of 0,1,2 so this leads to a common math problem with a very simple math formula.
See here: https://cbpowell.wordpress.com/2009/11/14/permutations-vs-combinations-how-to-calculate-arrangements/
for(int i=0;i<s.length;i++){
for(int j=i;j<s.length+i;j++) {
System.out.print(s[j%(s.length)]);
}
System.out.println();
}
Using mod is approppiate for this question. The indexes of the printed values for your first example are like this;
0 1 2
1 2 0
2 0 1
so if you write them like the following and take mod of length of the array (3 in this case) you will reach solution.
0 1 2
1 2 3
2 3 4
My assignment is to merge two arrays using int arrays that the user fills and we have to assume that there will be a maximum of 10000 inputs from the user, and the user inputs a negative number to stop. Then sort the array from least to greatest and print it out. Initially i thought that this would be quite easy but when i finished, i began getting outputs such as:
Enter the values for the first array, up to 10000 values, enter a negative number to quit: 1
3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
1
3
5
Second Array:
2
4
6
Merged Array:
6 1 2 3 4 5
as you can see, the six is out of place and i have no idea how to fix it. Here is the source code, i have included copious comments because I really want you guys to help me out to the best of your abilities. IF it's possible to use the same exact technique without implement new techniques and methods into the code please do so. I know there are methods in java that can do all of this in one line but it's for an assignment at a more basic level.
import java.util.Scanner;
public class Merge
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int [] first = new int[10000]; //first array, assume 10k inputs max
int [] second = new int[10000]; //first array, assume 10k inputs max
boolean legal = true; //WILL IMPLIMENT LATER
int end = 0; // set how many elements to put in my "both" array
int end2 = 0;// set how many elements to put in my "both" array
System.out.print("Enter the values for the first array, up to 10000 values, enter a negative number to quit");
//get values
for(int i = 0; i<first.length; i++)
{
first[i] = scan.nextInt(); //fill first with user input
if(first[i] <0) //if negative number, stop loop
{
end = i; //get position of end of user input
break;
}
}
System.out.println("Enter the values for the second array, up to 10000 values, enter a negative number to quit");
for(int i = 0; i<second.length; i++) //exact same as the first get values loop
{
second[i] = scan.nextInt();
if(second[i] <0)
{
end2 = i;
break;
}
}
System.out.print("First Array:\n");
for(int i = 0; i<first.length; i++) //print first array
{
if(i == end) //this prevents from printing thousands of zeros, only prints values that user inputed
break;
System.out.println(first[i] + " ");
}
System.out.print("Second Array:\n");
for(int i = 0; i<second.length; i++) //same as printing first array
{
if(i == end2)
break;
System.out.println(second[i] + " ");
}
int [] both = new int[(end)+(end2)]; //instanciate an int array to hold only inputted values from first[] and second[]
int [] bothF = new int[(end)+(end2)]; //this is for my simple sorter algotithm loop
for(int i = 0; i<both.length; i++) //fill both with the first array that was filled
{
both[i] = first[i];
}
int temp = end; // see below
for(int i = 0;i<both.length; i++) //fill array with the second array that was filled(starting from the end of the first array so that the first set is not overwritten
{
if(temp<both.length){ //this prevents an out of bounds
both[temp] = second[i];
temp++;}
}
//simple sorting algorithm
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
bothF[d] = both[d];
both[d] = both[i];
both[i] = bothF[d];
}
}
}
System.out.println("Merged Array:"); //print the results
for(int i = 0; i<both.length; i++)
{
System.out.print(both[i] + " ");
}
//System.out.println("ERROR: Array not in correct order");
}
Your sorting algorithm is faulty.
It's similar to selection sort, in that you take two elements and swap them if they're out of place. However, you don't stop the comparisons when you should: when the index d is less than the index i, the comparison-and-swap based on arr[d] > arr[i] is no longer valid.
The inner loop should terminate with i=d.
The logic of your sort goes something like this:
On the d-th loop, the elements at d+1 and to the right are correctly sorted (the larger numbers). This is true at the beginning, because there are 0 elements correctly sorted to the right of the right-most element.
On each of the outer loops (with the d counter), compare the d-th largest element slot with every unsorted element, and swap if the other element is larger.
This is sufficient to sort the array, but if you begin to compare the d-th largest element slot with already-sorted elements to its right, you'll end up with a larger number in the slot than should be. Therefore, the inner loop should terminate when it reaches d.
Sure, you can do it like this
for (int i = 0; i < end; i++) {
both[i] = first[i];
}
for (int i = 0; i < end2; i++) {
both[i + end] = second[i];
}
// simple sorting algorithm
for (int d = both.length - 1; d >= 0; d--) {
for (int i = 0; i < d; i++) {
if (both[i] > both[d]) {
int t = both[d];
both[d] = both[i];
both[i] = t;
}
}
}
Output(s) -
Enter the values for the first array, up to 10000 values, enter a negative number to quit3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
3
5
Second Array:
2
4
6
-1
Merged Array:
2 3 4 5 6
First I will start with some recommendations:
1.Give end1 and end2 the initial value as the array lengths.
The printing part - instead of breaking the loop - loop till i == end(if its not changed by the first part it will stay the array length).
One suggestion is to use a "while" statement on the user input to do the reading part (it seems cleaner then breaking the loop- but its OK to do it like you have done too).
Try to use more functions.
now to the main thing- why not to insert the numbers from both arrays to the join array keeping them sorted?
Guiding:
Keep a marker for each array.
Iterate over the new join array If arr1[marker1]> arr2[marker2]
insert arr2[marker2] to the joint array in the current position.
and add 1 to marker2. and the opposite.
(don't forget to choose what happens if the are equal).
This can be achieved because the arrays were sorted in the first place.
Have fun practicing!
I guess you have sort of a reverse "selection sort"-algorithm going on there. I made an class that run your code and printed out the output after every swap. Here is the code which is the same as you got in your application with the addition of print.
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
int temp = both[d];
both[d] = both[i];
both[i] = temp;
printArray(both);
}
}
}
and when we run this on an example array we get this output
[9, 8, 7, 6]=
-> 6879
-> 6789
-> 6798
-> 6978
-> 9678
The algorithm actually had the correct answer after two swaps but then it started shuffling them into wrong order. The issue is the inner for loops end parameter. When you have run the outer loop once, you can be certain that the biggest number is in the end. 'd' is here 3 and it will swap out a bigger number every time it encounters it. the if clause comparisions in the first loop is 6-9 (swap), 9-8, 9-7, 9-9. All good so far.
Potential problems comes in the second iteration with 'd' as 2. Array is now [6,8,7,9] and comparisons are 7-6, 7-8 (swap with result [6,7,8,9]), 8-8, 8-9 (swap!!) resulting in [6,7,9,8]. the last swap was the problematic one. We knew that the biggest number was already in the last spot, but we still compare against it. with every gotrough of the whole inner loop it will always find the biggest number (and all other bigger than both[d] that is already in place) and swap it to some wrong position.
As we know that the biggest number will be last after one iteration of the outer loop, we shouldn't compare against it in the second iteration. You sort of lock the 9 in the array and only try to sort the rest, being in this case [6,8,7] where d = 3, value 7. hence, your inner loop for(int i = 0; i<both.length; i++) becomes for(int i = 0; i<=d; i++). As an added bonus, you know that in the last iteration i==d, and thus the code inside it, if(both[d]<both[i]) will never be true, and you can further enhance the loop into for(int i = 0; i<d; i++).
In your algorithm you always do four comparisons in the inner loop over four iterations of the outer loop, which means there is a total of 16 comparisons. if we use the i<d we'll just do three comparisons in the inner loop on the first iteration of the outer loop, then two, then one. This brings it to a total of six comparisons.
Sorry if too rambling, just wanted to be thorough.