import java.io.*;
import java.util.*;
class Graph
{
private int V; // No. of vertices
private LinkedList<Integer> adj[]; //Adjacency Lists
private LinkedList<Integer> path[];
Graph(int v)
{
V = v;
adj = new LinkedList[v];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList();
path = new LinkedList[v];
for(int i=0;i<v;++i)
adj[i]=new LinkedList();
}
void addEdge(int v,int w)
{
adj[v].add(w);
}
// prints BFS traversal from a given source s
void BFS(int s,int d)
{
boolean visited[] = new boolean[V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s]=true;
queue.add(s);
path[s].addLast(s);
while (queue.size() != 0)
{
s = queue.poll();
//System.out.print(s+" ");
Iterator<Integer> i = adj[s].listIterator();
while (i.hasNext())
{
int n = i.next();
if (!visited[n])
{
visited[n] = true;
queue.add(n);
path[n]=path[s];
path[n].addLast(n);
}
}
}
System.out.print("Following is the path from source to destination\n");
while(path[d].size()!=0)
{
int xyz=path[d].getFirst();
path[d].poll();
System.out.print(xyz+" ");
}
}
// Driver method to
public static void main(String args[])
{
Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
System.out.println("Following is the desired path\n");
g.BFS(2,3);
}
}
I need to get the shortest path between nodes 2 and 3.
You're attempting to add an element to a linked list that is null. You need to initialize the linked list at index s before you can add to it.
path[s] = new LinkedList();
path[s].addLast(s);
Additionally, your code is failing because you don't clone the path array when setting the value of path[n]:
path[n]=path[s];
You need to change this to:
path[n]= (LinkedList) path[s].clone();
This way the list for n won't retain a reference to the list of s. Currently, the reference is retained, so that whenever you add something to the list for n, that thing will also be added to s.
As there is no information what exactly isn't behaving as expected, it is a bit difficult to say what the error is. But I see two problems with the code:
First, you don't initialize the elements of the path. Instead, in the constructor you initialize the elements of adj twice. So, you should replace one of the lines that say
for(int i=0; i<v; ++i)
adj[i] = new LinkedList();
with
for(int i=0; i<v; ++i)
path[i] = new LinkedList();
or you can just delete the two lines as you will see now:
The second problem is that you set the different elements of path as the reference to another LinkedList and edit it:
path[n] = path[s];
path[n].addLast(n);
This has as result that every element of path uses the same LinkedList with the same elements. Instead you should create a new LinkedList containing the same elements:
path[n] = new LinkedList(path[s]);
path[n].addLast(n);
EDIT: As Soggiorno said in his answer, you must at least initialize path[s] at the beginning of the BFS-method before adding an element to it:
path[s] = new LinkedList();
path[s].addLast(s);
If you do the initialization for all the elements of path this isn't needed, of course.
Related
I have found a few questions similar to the problem I am facing, but I couldn't find solution.
Example: Incompatible types List of List and ArrayList of ArrayList, Not able to understand how to define a List of List in java
The program should return list of lists. So, I declared a list of lists and then trying to add arraylists to it.
allsubsets = new ArrayList<List<Integer>>();
But, when I am trying to access each arraylist item from the list of lists as below, I get the error: incompatible types: List<Integer> cannot be converted to ArrayList<Integer>
for(ArrayList<Integer> subset:allsubsets)
When I try to convert the line to for(List<Integer> subset:allsubsets), it throws error that add, addAll don't exist for List type, which makes sense. Please help me understand how to access elements of list of lists in this case.
public List<List<Integer>> subsets(int[] nums) {
List<Integer> arrayList = new ArrayList<Integer>();
for(int i:nums) {
arrayList.add(i);
}
return subsets(arrayList,nums.length);
}
public List<List<Integer>> subsets(List<Integer> arrayList, int index) {
List<List<Integer>> allsubsets;
if(index == -1) {
allsubsets = new ArrayList<List<Integer>>();
allsubsets.add(new ArrayList<Integer>());
}
else {
allsubsets = subsets(arrayList, index-1);
int item = arrayList.get(index);
List<List<Integer>> moresubsets = new ArrayList<List<Integer>>();
for(ArrayList<Integer> subset:allsubsets) {
//The line above throws error as I created list of lists
List<Integer> newsubset = new ArrayList<Integer>(); //create new subset
newsubset.addAll(subset); // add all old items
newsubset.add(item); // add new item
moresubsets.add(newsubset); //add subset to moresubsets
}
allsubsets.add(moresubsets); // add to actual one
}
return allsubsets;
}
Note: If I change the return type to arraylist of arraylists, it works for me. But, I want to make it work for the list of lists
Correct way to iterate your list of list should be:
for(List<Integer> subset:allsubsets) {
instead of:
for(ArrayList<Integer> subset:allsubsets) {
List<List<Integer>> allsubsets is declared as List of List, but the implementation is unknown.
Only you know the type of nested List is ArrayList, so either change foreach to use List<Integer> or manually cast your List<Integer> to ArrayList<> (this is not preferred)
One more thing:
allsubsets.add(moresubsets); // add to actual one
This try to add a List of List (List<List<Integer>>) as element which should be List<Integer> hence compile error.
Change that statement to:
allsubsets.addAll(moresubsets);
Let's try expanding that enhanced for loop into more basic components:
for(ArrayList<Integer> subset:allsubsets) {
//The line above throws error as I created list of lists
}
// this is roughly equivalent to
Iterator<List<Integer>> it = allsubsets.iterator();
while(it.hasNext()) {
ArrayList<Integer> subset = it.next(); // Error
// Since the iterator was defined as an iterator to a List<List<Integer>>,
// it.next() will return the next element in allsubsets
// which happens to be an List<Integers>.
// You can't assign a reference of a parent type to a child. However
// the opposite is perfectly fine, assigning a reference of a child type
// to a parent.
// If we change subset to be a List<Integer> i.e.
// for(List<Integer> subset : allsubsets)
// then we are assigning a reference of a List<Integer> to a List<Integer>
// so no problem.
}
I prefer to share with you the code I did for managing the same type of Object List you are trying to handle. Hope this helps.
public static void main(String[] args) {
List<List<Integer>> allsubsets = setSubsets();
List<List<Integer>> allsubsets2 = new ArrayList<>();
allsubsets2.addAll(allsubsets);
int i= 0;
for (List<Integer> test : allsubsets2) {
System.out.println(i + " Lista");
for (Integer integer : test) {
System.out.println(integer);
}
i++;
}
}
public static List<List<Integer>> setSubsets() {
List<List<Integer>> allsubsets = new ArrayList<List<Integer>>();
List<Integer> listInteger1 = new ArrayList<>();
List<Integer> listInteger2 = new ArrayList<>();
for (int i = 0; i < 100; i++) {
listInteger1.add(i);
}
for (int i = 1010; i < 1110; i++) {
listInteger2.add(i);
}
allsubsets.add(listInteger1);
allsubsets.add(listInteger2);
return allsubsets;
}
So the issue I'm having is after copying the 2d arraylist, changing the element from one 2d arraylist affects the other 2d arraylist. I want them to be completely separate in memory.
First example shows how it works correctly with 1d arraylists...
import java.util.ArrayList;
public class QuickTest {
public static void main(String[] args) {
ArrayList<Integer> firstList = new ArrayList<>();
ArrayList<Integer> secondList = new ArrayList<>();
Integer counter = 2;
for(int arrI = 0; arrI < 4; arrI++, counter+=2){
firstList.add(counter);
}
secondList = new ArrayList<>(firstList);
System.out.println("firstList.get(2) = " + firstList.get(2));
System.out.println("secondList.get(2) = " + secondList.get(2));
firstList.set(2, 7);
System.out.println("firstList.get(2) = " + firstList.get(2));
System.out.println("secondList.get(2) = " + secondList.get(2));
}
}
Expected output:
Notice how the element from the first arraylist is changed but not the second arraylist element is not changed. This is good and what we want.
Now to try and copy the 2d arraylists...
import java.util.ArrayList;
public class QuickTest {
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
Integer counter = 2;
for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
firstTwoDimList.get(arrI).add(counter);
counter+=2;
firstTwoDimList.get(arrI).add(counter);
}
secondTwoDimList = new ArrayList<>(firstTwoDimList);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
firstTwoDimList.get(1).set(0, 7);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
}
}
Unexpected output:
Anyone have any idea what the reason for this is, and what the best solution would be?
This is what is happening in the 1D array list case, in terms of references:
This is what is happening in the 2D array list case:
This means that when you copy an array list using this:
new ArrayList<>(someOldArrayList)
the items themselves don't get copied, only a new array list object is created, referring to all the items in the old array list.
In the second case, you are only changing what array list 2's items are, but index 1 of first list and second list refers to the same array list 2.
To fix this, you need to copy the array lists inside first list and second list as well. One way to do this:
secondList = new ArrayList<>(firstList.stream().map(x -> new ArrayList<>(x)).collect(Collectors.toList()));
You should iterate through the size of the first dimension of the firstTwoDimArray and add new reference of each second dimension to the secondTwoDimArray. i.e.
for(int index = 0; index < firstTwoDimList.size(); index++) {
secondTwoDimList.add(new ArrayList<Integer>(firstTwoDimList.get(index)));
}
The difference between your first and second example is that in the second one you use get(). This get() returns a new variable, so you assign the integers to it and not to the original ArrayList.
If you want to assign a value:
firstTwoDimList.set(1, new ArrayList<Integer>(Arrays.asList(0, 7)));
I guess I was looking for something like this...
import java.util.ArrayList;
public class QuickTest {
public static ArrayList<ArrayList<Integer>> getTwoDimArrListCopy(ArrayList<ArrayList<Integer>> original){
ArrayList<ArrayList<Integer>> copy = new ArrayList<>();
for (ArrayList<Integer> arr: original){
copy.add(new ArrayList<Integer>(arr));
}
return copy;
}
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
Integer counter = 2;
for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
firstTwoDimList.get(arrI).add(counter);
counter+=2;
firstTwoDimList.get(arrI).add(counter);
}
secondTwoDimList = getTwoDimArrListCopy(firstTwoDimList);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
firstTwoDimList.get(1).set(0, 7);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
}
}
I was just hoping there was a built in library that would do that getTwoDimArrListCopy() function for me...
I am writing a code which needs to copy an arraylist but i am getting wrong answer after debugging i found that changing a copy of arraylist is changing the original arraylist but i am not able to figure out why
static void iterDeep(int level,ArrayList<ArrayList<Integer>> current){
if(current.equals(dest)){
found = 1;
printPath(current);
return;
}
if(level <= 0)
return;
for(int i=0;i<3;i++){
for(int j=0;j<2;j++){
ArrayList<ArrayList<Integer>> adj = new ArrayList<ArrayList<Integer>>(current);
if(j == 0){
for(int k=0;k<3;k++){
adj.get(k).set(i , current.get( (3+k-1)%3 ).get(i));
// Here i am changing adj values but values in current are getting changed
}
if(!map.containsKey(adj)){
map.put(adj,current);
iterDeep(level - 1 , adj);
}
}else{
for(int k=0;k<3;k++){
adj.get(k).set(i , current.get( (k+1)%3 ).get(i));
}
if(!map.containsKey(adj)){
map.put(adj,current);
iterDeep(level - 1 , adj);
}
}
}
}
return;
}
This line
ArrayList<ArrayList<Integer>> adj = new ArrayList<ArrayList<Integer>>(current);
produces a shallow copy of the list, meaning that although adding/removing elements of adj are not reflected in current, changing elements themselves have an effect on ArrayList<Integer> elements of both lists.
You need to make a method that creates a deep copy of the list, i.e. copies each individual list element into elements of adj:
static ArrayList<ArrayList<Integer>> deepCopy(ArrayList<ArrayList<Integer>> orig) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
for (ArrayList<Integer> inner : orig) {
res.add(new ArrayList<Integer>(inner));
}
return res;
}
i have an arrayList ( named error_dub ) i want to print the duplicates only one time here is my code
for(x=0 ; x<=error_dub.size()-1 ; x++){
for(int h=x+0 ; h<=error_dub.size() ; h++){
if(error_dub.get(x).equals(error_dub.get(h) && x!=h){
System.out.println(error_dub.get(x)+" is duplicated ");
}
}
}
here the line is printed more than once so how can i printed only once ?
Use two sets (this assumes X is the class of your object):
// Returns a set of all duplicates in a list
public Set<X> getDuplicates(final List<X> list)
{
final Set<X> dups = new HashSet<X>();
final Set<X> set = new HashSet<X>();
/*
* Cycle through all elements in the original list. Add it to "set":
*
* - if the .add() method returns true, this is the first time the element is seen;
* - if it returns false, then this is not the first time, it is a duplicate:
* add it to "dups".
*/
for (final X element: list)
if (!set.add(element))
dups.add(element);
return dups;
}
Set's .add() will return false if the set is not modified as a result of the operation, which means if the element was already there.
Copy/paste that function into your existing code and replace the snippet above with:
for (final X dup: getDuplicates(error_dub))
System.out.println(dup + " is duplicated");
Important note: the getDuplicates() function as it is written will NOT respect element order. If order matters to you, replace dups with a LinkedHashSet instead of a HashSet.
you can use .add() method of set to check for duplicates. Method posted below adds list elements to set1. If element is a duplicate (.add() returns true), then element is adde to setToReturn
public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{
final Set<Integer> setToReturn = new HashSet();
final Set<Integer> set1 = new HashSet();
for (Integer yourInt : listContainingDuplicates)
{
if (!set1.add(yourInt))
{
setToReturn.add(yourInt);
}
}
return setToReturn;
}
ArrayList<String> ar=new ArrayList<String>();
ArrayList<String> ar2=new ArrayList<String>();
ar.add("1");
ar.add("2");
ar.add("3");
ar.add("4");
ar.add("5");
ar.add("1");
ar.add("2");
ar.add("1");
for(int x=0;x<ar.size();x++)
{
if(!ar2.contains(ar.get(x)))
{
for(int y=x+1;y<ar.size()-1;y++)
{
if((ar.get(y).equals(ar.get(x))))
{
System.out.print("repeating "+ar.get(x));
ar2.add(ar.get(x));
break;
}
}
}
}
you can do like this.
//method to identify the duplicate elements in array list
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
public class Dup
{
public static void main(String[] args)
{
ArrayList<Integer> a=new ArrayList<Integer>();
System.out.println("enter elements");
int g;
Scanner b= new Scanner(System.in);
for(int i=0;i<10;i++)
{
g=b.nextInt();
a.add(g);
}
HashSet<Integer> c=new HashSet<Integer>();
ArrayList<Integer> d=new ArrayList<Integer>();
for (Integer y : a)
{
if (c.contains(y))
{
d.add(y);
}
else
c.add(y);
}
System.out.println("original elements are:"+c);
System.out.println("duplicate elements are:");
for(Integer h:d)
{
System.out.println(h);
}
}
}
The lists are sorted the way they are supposed to but when I try to merge the two lists together in my makeUnion it prints out the list is empty. can anyone help me and tell my why? in main when I try SortedLinkedList merge = sortedNames1.makeUnion(sortedNames2) I get "Empty list".
public class SortedLinkedList<T extends Comparable<? super T>>
extends LinkedList<T>
{
private LinkedList<T> list; //the sorted list
//the constructor
public SortedLinkedList(LinkedList<T> in)
{
if(in.isEmpty())
{
System.out.println("Empty list");
}
if(in.size() < 2)
{
return;
}
else
{
list = new LinkedList<T>();
for(int i = 1; i < in.size(); i++)
{
T temp = in.get(i);
int j = i;
while(j > 0 && in.get(j - 1).compareTo(temp) > 0)
{
in.set(j, in.get(j-1));
j--;
}
in.set(j, temp);
}
for(T elements : in)
{
list.add(elements);
}
}
}
//return the union of the sorted linked lists this and other
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
SortedLinkedList<T> first = new SortedLinkedList<T>(other);
SortedLinkedList<T> second = new SortedLinkedList<T>(list);
SortedLinkedList<T> UnionList = null;
int i = 0;
int j = 0;
while(i<first.size() && j<second.size())
{
if(first.get(i).compareTo(second.get(j)) <= 0)
{
UnionList.add(first.get(i));
i++;
}
else
{
UnionList.add(second.get(j));
j++;
}
}
if(i == first.size())
{
for(int k = j; k<second.size(); k++)
{
UnionList.add(second.get(k));
}
}
else if(j == second.size())
{
for(int x = i; x<first.size(); x++)
{
UnionList.add(first.get(x));
}
}
return UnionList;
}
//print the items int list
public void print()
{
ListIterator itr = list.listIterator();
while(itr.hasNext())
{
System.out.println(itr.next());
}
}
}
SortedLinkedList<T> UnionList = null;
You can't call UnionList.add() if UnionList is null. You will need to allocate a new list before you can add things to it.
Actually, I think your original problem might be that SortedLinkedList both extends LinkedList and also contains an instance of a LinkedList. You should choose one or the other, but not both. Your code sometimes accesses one list, and sometimes the other, so one list appears empty because you've added items to the other list.
You don't initialize UnionList before you start using it.
SortedLinkedList<T> UnionList = null;
should read
SortedLinkedList<T> UnionList = new SortedLinkedList<T>();
As a bonus, ListIterator ought to be ListIterator<T> so that the right toString() method is used. As it is, you'll be calling Object.toString().
Because you used inheritance instead of delegation. You inherit LinkedList, and the only thing you do is define a constructor which adds the content of an unsorted list to a new one, in the appropriate order. But you don't override the size method, so this method is inherited from LinkedList, which doesn't care about your internal sorted list and thus always returns 0.
Extending a collection is, most of the time, a bad idea. In this case, it's a particularly bad idea because it's impossible to have a sorted LinkedList that respects the LinkedList API. Suppose your list contains A, B and C, and you call addFirst("Z") on it. Where will you put Z, if at the beginning, your list is not sorted anymore. If at the end, you don't respect the contract of addFirst.
Just use linked lists (instead of extending them), and sort them. You could just do :
LinkedList list = new LinkedList(someUnsortedList);
Collections.sort(list); // now the list is sorted
list.addAll(someOtherList);
Collections.sort(list); // now both lists are merged, and the resulting list is sorted.