Duplicate linkedList - java

I want to duplicate the elements in a linked list. This is what I have tried:
public class duplicate {
public static void main(String[] args) {
LinkedList <Integer> list = new LinkedList<Integer>() ;
list.add(2);
list.add(3);
list.add(4);
list.add(1);
list.add(0);
for( int i= 0 ; i<list.size(); i++) {
list.addAll(list);
System.out.println(list);
break;
}
}
}
But I got an infinite loop.

Firstly, your code runs just fine (the break prevents the infinite loop, see JLS-The break Statement).
Now, you don't need to for-loop over the list because List.addAll already
Appends all of the elements in the specified collection to the end of
this list, in the order that they are returned by the specified
collection's iterator (optional operation) (...)
So, just by doing this you're fine:
LinkedList <Integer> list = new LinkedList<Integer>() ;
//... code omitted (adds every number)
list.addAll(list);
However, if you want to use List.add instead of List.addAll you can do it like this (need to use for-loop):
LinkedList <Integer> list = new LinkedList<Integer>() ;
//... code omitted (adds every number)
int initialSize = list.size();
for( int i = 0 ; i < initialSize; i++) {
list.add(list.get(i));
}
System.out.println(list);

you are adding the list elements again and again in the for loop.
for(int i= 0 ; i < list.size(); i++) {
list.addAll(list);
System.out.println(list);
}
Every time it will grow & which leads the size to grow for each iteration. correct the step. Either use a local variable to store the size or change your logic

You can simply do list.addAll(list);.
If you want to use the add method as an exercise, you need to be careful to save the original size of the list before you start iterating. You can do it in the initialization part of your for loop:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(2, 3, 4, 1, 0));
for (int i = 0, size = list.size(); i < size; i++)
list.add(list.get(i));
System.out.println(list);
assert list.equals(Arrays.asList(2, 3, 4, 1, 0, 2, 3, 4, 1, 0));
}
Now you'll notice the above uses ArrayList, rather than LinkedList. In general, you should prefer ArrayList. Even the author of Java's LinkedList says he doesn't use it. See also this SO question about ArrayList vs LinkedList.
If you have to use LinkedList, you can just replace the second line from the above to this:
List<Integer> list = new LinkedList<>(Arrays.asList(2, 3, 4, 1, 0));
The rest of the code can remain unchanged. However, if you have a very long list, then using the get(index) method of the LinkedList class can reduce performance. With LinkedList, you get higher performance if you iterate (using LinkedList.iterator() or an enhanced for loop, than by using a plain for loop with get() calls. But you can't iterate over the list while adding to it, as you'll then get a ConcurrentModificationException. Instead, you can copy the linked list to an array and iterate over that, while adding to the list:
public static void main(String[] args) {
List<Integer> list = new LinkedList<>(Arrays.asList(2, 3, 4, 1, 0));
for (Integer element : list.toArray(new Integer[0])) {
list.add(element);
}
System.out.println(list);
assert list.equals(Arrays.asList(2, 3, 4, 1, 0, 2, 3, 4, 1, 0));
}

Related

Emptying an ArrayList of LinkedList back into an Array

I am trying to remove elements of an ArrayList of LinkedLists back into an Array. I am getting caught on a element not found exception.
ArrayList<LinkedList<Integer>> stacks = new ArrayList<LinkedList<Integer>>(3);
int[] arr = new arr[5];
stacks.get(0).add(22);
stacks.get(0).add(1);
stacks.get(0).add(7);
stacks.get(1).add(111);
stacks.get(2).add(123);
for (int i = 0; i < arr.length; i++)
{
while (!stacks.isEmpty())
{
arr[i++] = stacks.get(i).remove();
}
}
I would operate under the assumption that the while is NOT empty would account for this. I am curious why it will not successfully copy the contents over?
There are several issues in your code.
int[] arr = new int[5]; // not new arr[]
You are not adding a LinkedList to the ArrayList. You need to add LinkedLists first and then add items to stacks.
Your loop is completely wrong, I've rewritten it.
ArrayList<LinkedList<Integer>> stacks = new ArrayList<>(3);
int[] arr = new int[5];
stacks.add(new LinkedList<>());
stacks.add(new LinkedList<>());
stacks.add(new LinkedList<>());
stacks.get(0).add(22);
stacks.get(0).add(1);
stacks.get(0).add(7);
stacks.get(1).add(111);
stacks.get(2).add(123);
int count = 0;
for (LinkedList<Integer> stack : stacks) {
for (Integer integer : stack) {
arr[count++] = integer;
}
}
System.out.println(Arrays.toString(arr));
This will do it. This example uses ArrayLists but it will also work with LinkedLists or anything that implements the List interface.
Create the list of lists.
ArrayList<List<Integer>> stacks =
new ArrayList<>(List.of(List.of(22, 1, 7),
List.of(111, 112), List.of(44, 123, 99)));
And convert to int array
int[] ints = stacks
.stream() // convert to a stream of lists
.flatMap(List::stream) // combine all lists to one list of Integers
.mapToInt(Integer::intValue)// convert Integers to ints
.toArray(); // and output to an array.
System.out.println(Arrays.toString(ints));
Prints
[22, 1, 7, 111, 112, 44, 123, 99]

why i'm getting heap space error in java?

I'm trying to Write a method called scaleByK that takes an ArrayList of integers as a parameter and replaces every integer of value k with k copies of itself. For example, if the list stores the values [4, 1, 2, 0, 3] before the method is called, it should store the values [4, 4, 4, 4, 1, 2, 2, 3, 3, 3] after the method finishes executing. Zeroes and negative numbers should be removed from the list by this method.
the problem is that I'm getting error of java heap space.
public class Lab1construct2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(2);
list.add(0);
list.add(3);
Lab1construct2 myprogram = new Lab1construct2();
myprogram.scalebyk(list);
System.out.print(list);
}
public void scalebyk(ArrayList<Integer> list) {
int j = 0;
while( j < list.size()) {
int elm =list.get(j);
for(int i=1; i<=elm; i++) {
list.add(elm);
}
j = j + list.get(j);
}
}
}
You keep inserting copies of processed elements to the back of the same list which you are reading. So after you done processing of the original elements you start to process their copies, then copies of their copies, etc. This never stops and you get heap overflow. Create a new list which will keep the result and return it from the method, don't modify the current list.
public List<Integer> scalebyk(ArrayList<Integer> list) {
List<Integer> result = new ArrayList<Integer>();
for (Integer element : list) {
for (int i = 0; i < element; i++) {
result.add(element);
}
}
return result;
}
It is because your code would never terminate. Following would be the flow of your scaleByk function:
First element is 4, j=0 hence 4 new elements will be added to the list with the value of 4
j=4 but is still less than list.size() as size is increased by 4 in the previous step. Again it will trigger the addition of 4 elements with value 4.
This cycle will keep repeating till you run out of the heap space allocated to your program.

How to get difference from 2 arrays for each values

How can I get the difference from 2 arrays
Input:
List<Integer> bookingList = (3,4,5,6,5,5);
List<Integer> bookedList = (1,2,3,2,3,4);
What I want to do is pointwise subtraction
bookingList.get(i) - bookedList.get(j)
//i is the position
//j is the position
The result should be a new List with the following content:
List<Integer> finalList = (2,2,2,4,2,1)
Here you are:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
caluclateFinalList();
}
private static void caluclateFinalList() {
List<Integer> bookingList = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 5, 5));
List<Integer> bookedList = new ArrayList<>(Arrays.asList(1, 2, 3, 2, 3, 4));
// Output list
List<Integer> finalList = new ArrayList<>(bookingList.size());
// Loop
for (int position = 0; position < bookedList.size(); position++) {
// Calculate result
int result = bookingList.get(position) - bookedList.get(position);
// Add result to final list
finalList.add(result);
}
// Print final list to the console
System.out.println(finalList);
}
}
If the lists are guaranteed to be the same size then you can simply do a for loop.
List<Integer> results = new ArrayList(bookingList.size());
for(int i= 0; i < bookingList.size(); i++) {
results.add(bookingList.get(i) - bookedList.get(i));
}
return results;
This gives you the differences inside results and within O(n) where n is the size of the arrays.
If the arrays are not the same size, you obviously need to check for some index bounds. I'm not sure whether you want to consider the excess elements and just add them to the result, or if you want to discard them, but a simple modification to the algorithm above can get your there.

Getting IndexOutOfBoundException

why does following main method gives IndexOutOfBoundException at list.add(1, 2)?
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1, 2);
int total = list.get(0);
System.out.println(total);
}
You can't add an element at index 1 when it the ArrayList is empty. It starts at 0, or just use add.
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
int total = list.get(0); // <-- You even use 0 here!
System.out.println(total);
}
Per the ArrayList#add(int index, E element) javadoc,
Throws:
IndexOutOfBoundsException - if the index is out of range
(index < 0 || index > size())
When size == 0, the index 1 is out of range.
Here's the problem:
list.add(1, 2);
To fix it, do this:
list.add(0, 2);
Or even simpler, this:
list.add(2);
Remember: in Java, lists an arrays start at index 0, you'll get an error if you try to add an element at index 1 in an empty list.
List maintains the insertion order.
We are trying to add an element at index 1, when the list is empty, that is why it results in java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
Quick Solutions:-
Add elements in the list using add() method of the Collection interface.
List list = new ArrayList();
list.add(1);
list.add(2);
Add elements to the list using add(int index, T t) method of the List interface.
List list = new ArrayList();
list.add(0, 1); // Filling 0th index with value 1.
list.add(1, 2); // Filling 1th index with value 2.

Is there a way to find common elements in multiple lists?

I have a list of integer arrays. I need to find the common elements between those. What I can think of is an extension of what is listed in Common elements in two lists
Example would be
[1,3,5],
[1,6,7,9,3],
[1,3,10,11]
should result in [1,3]
There are no duplicates in the arrays as well.
Is there a straight forward way to do this?
You can transform the lists to sets, and then use Set.retainAll method for intersection between the different sets.
Once you intersect all sets, you are left with the common elements, and you can transform the resulting set back to a list.
You can use Set's intersection method offered by Guava, Here is a little example :
public <T> Set<T> intersection(List<T>... list) {
Set<T> result = Sets.newHashSet(list[0]);
for (List<T> numbers : list) {
result = Sets.intersection(result, Sets.newHashSet(numbers));
}
return result;
}
Hope that could help you
We can use retainAll method of Collections. I initialised my commons arraylist with the first array list and called this for each remaining arraylists.
List<List<Integer>> lists = new ArrayList<List<Integer>>();
lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 5)));
lists.add(new ArrayList<Integer>(Arrays.asList(1, 6, 7, 9, 3)));
lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 10, 11)));
List<Integer> commons = new ArrayList<Integer>();
commons.addAll(lists.get(1));
for (ListIterator<List<Integer>> iter = lists.listIterator(1); iter.hasNext(); ) {
commons.retainAll(iter.next());
}
System.out.println(commons);
System.out.println(lists.get(1));
with Java 8
ArrayList retain = list1.stream()
.filter(list2::contains).filter(list3::contains).collect(toList())
If you are looking for a function that returns elements that exist in all lists,
then the straight forward & simple way is building a statistic { < member, occurences > }
The condition here is no duplicates among the same list,
private Set<Integer> getCommonElements(ArrayList<Integer[]> idList)
{
MapList<Integer,Short> stat = new MapList<Integer,Short>();
// Here we count how many times each value occur
for (int i = 0; i < idList.size(); i++)
{
for (int j = 0; j < idList.get(i).size; j++)
{
if (stat.containsKey(idList.get(i)[j]))
{
stat.set(idList.get(i)[j], stat.get(idList.get(i)[j])+1);
}
else
{
stat.add(idList.get(i)[j], 1);
}
}
}
// Here we only keep value that occured in all lists
for (int i = 0; i < stat.size(); i++)
{
if (stat.get(i) < idList.size())
{
stat.remove(i);
i--;
}
}
return stat.keySet();
}
public class ArrayListImpl{
public static void main(String s[]){
ArrayList<Integer> al1=new ArrayList<Integer>();
al1.add(21);al1.add(23);al1.add(25);al1.add(26);
ArrayList<Integer> al2=new ArrayList<Integer>();
al2.add(15);al2.add(16);al2.add(23);al2.add(25);
ArrayList Al3=new ArrayList<Integer>();
al3.addAll(al1);
System.out.println("Al3 Elements :"+al3);
al3.retainAll(al2); //Keeps common elements of (al1 & al2) & removes remaining elements
System.out.println("Common Elements Between Two Array List:"+al3);
}
}
If you are using JAVA 8 streams. Then using stream reduce operation we can achieve the same.
Considering your example: Let's say
a = [1,3,5], b = [1,6,7,9,3] and c = [1,3,10,11]
List<Integer> commonElements = Stream.of(a,b,c)
.reduce((s1,s2) -> {
s1.retainAll(s2);
return s1;
}).orElse(Collections.emptyList());
Keep in mind that after running this operation a will get modified with common values as well. So you will lose the actual value of a.
So elements of a and the result elements of commonElements will be essentially the same after running this operation.
Giving some another alternative code using retainAll capability of Set
public List getCommonItems(List... lists) {
Set<Integer> result = new HashSet<>(lists[0]);
for (List list : lists) {
result.retainAll(new HashSet<>(list));
}
return new ArrayList<>(result);;
}
Usage:
List list1 = [1, 2, 3]
List list2 = [3, 2, 1]
List list3 = [2, 5, 1]
List commonItems = getCommonItems(list1, list2, list3)
System.out.println("Common items: " + result);
Result:
commonItems: [1, 2]
public class commonvalue {
Public static void MyMethod(){
Set<integer> S1 = new set<integer>{1,3,5};
Set<integer> S2 = new set<integer>{1,6,7,9,3};
Set<integer> S3 = new set<integer>{1,3,10,11};
s2.retainall(s1);
s3.retainall(s2);
system.debug(s3);
}
}

Categories