linked-list interview question - java

This was the question asked in interview.Can anybody help me out it in implementing in java
Given 2 linked lists(which need not have unique elements) find intersection point in the form of Y.(it can be anywhere--middle or tail)

If the length of the lists is O(N), this solution is O(N) with O(1) space.
FUNCTION length(LIST list) : INT
// returns number of nodes until the end of the list
FUNCTION skip(LIST list, INT k) : LIST
// return the sublist of list, skipping k nodes
FUNCTION intersection(LIST list1, list2) : LIST
// returns the sublist where the two lists intersects
INT n1 = length(list1);
INT n2 = length(list2);
IF (n1 > n2) THEN
list1 = skip(list1, n1-n2)
ELSE
list2 = skip(list2, n2-n1)
WHILE (list1 != list2)
list1 = skip(list1, 1)
list2 = skip(list2, 1)
RETURN list1
Essentially, traverse each lists to find how many nodes there are. Then, skip enough elements from the longer list so that now you have lists of the same length. Then, in-sync, move forward step-by-step until the two lists meet.

http://java.sun.com/docs/books/tutorial/collections/interfaces/set.html
I don't have a good example at the moment, but I believe he's referring to this:
"The intersection of two sets is the set containing only the elements common to both sets."
Where 'sets' can also be Lists, etc.
Java has built in methods for this.
Say you have a List list, you would do something like this:
list.removeAll(list2);
or
list.retainAll(list2);
retainAll will you give you the 'intersection', removeAll gives you the difference between the two lists.

According to #Lord Torgamus question, here is a suggested java algorithm.
Suppose you have two java Collection objects (and LinkedList, as an implementor of List, is also an implementor of Collection). To find their intersection, you only have to call Collection#retainAll method on the first object giving the second one as an argument.

Related

Java 8 String Comparison

I have two list of strings.
I want to check if any string from one list is available in another list.
Have used below approach which fails.
Please let me know a better approach
List<String> mylist = Arrays.asList(stringArray1);
List<String> items = Arrays.asList(stringArray2);
return mylist.stream().anyMatch(t->items.stream().anyMatch(t::contains));
If you want to find if any element in mylist exists in items, you can first turn items into a Set:
Set<String> setOfItems = new HashSet<>(items);
Then, you can simply iterative over mylist and check if any element is contained in setOfItems.
mylist.stream().anyMatch(setOfItems::contains);
This brought your O(n * k) problem down to O(n + k) where n and k are the sizes of mylist and items, respectively.

Deleting items from a list according to items in another list

Suppose I have an ArrayList of Child objects called children.
ArrayList<Child> children = new ArrayList<>(data);
Now I have a List of integers which are some of the index for children in children.
List<Integer> items = new ArrayList<>(data2);
What would be the most efficient method to delete all children in children that have indexes that match integers in items?
You could create a list of objects to remove, then use ArrayList's removeAll() method.
Try something like this:
ArrayList<Child> toRemove = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
toRemove.add(children.get(items.get(i)));
}
children.removeAll(toRemove);
Hope this helps.
If items is not sorted (greater value first): Collections.sort(items, Collections.reverseOrder());
Then:
for (Integer i : items) {
children.remove(i);
}
The best approach is to create a new list with the elements that pass your condition.
As an alternative to aurelianus' answer above, to consider for your use case:
Sort the items array, then remove the Child objects from the children array in descending order of the indexes.
Cost considerations:
sorting the list of indexes - depends on the number of indexes to remove whether that's a concern.
For every Child object removed all children with higher indexes are shifted by one in the backing array. I suspect this is done with a System.arraycopy(), which would be quite efficient. Still, the cost rises with the number of elements to remove and the number of children with higher indexes.
memory is used in-place.
In favor of creating a new, filtered list and treating the old list as immutable, here is how you could do that in Java 8:
List<Child> collect = IntStream.range(0, children.size())
.filter(i -> !items.contains(i))
.mapToObj(children::get)
.collect(Collectors.toList());

How do I extract the K "smallest" elements from a list of objects?

I'm looping through a List to find a particular entry, then assigning that to a variable and trying to remove it later. It's easier to demo than to explain.
ArrayList<Example> list1 = populate();
Example ex1 = list1.get(0);
Example ex2 = ex1;
list1.remove(ex2);
I know this likely has something to do with Java's inability to handle pointers, but a viable solution would be great.
Edit: To elaborate, this is a brief example of my code rather than giving you the full thing. What I'm doing is iterating through a list to find the lowest 10 numbers. My technique is to go through the list, find the lowest and add it to another list, then remove that number from the original list and repeat. But my list is made of objects which have an int value inside them, rather than a list of integers.
for(0 to 9){
for(0 to list.size){
if(list.get(x) < smallest)
smallest = list.get(x)
}
smallestList.add(smallest);
list.remove(smallest)
}
I would sort the list. Then, I would create a list with those 10 smallest objects and change the original list list1 to contain the remaining objects. Something like:
Collection.sort(list1);
ArrayList<Example> yourSmallestElements = (ArrayList<Example>)(list1.sublist(0, 9).clone());
list1.removeAll(yourSmallestElements);
NOTE: I cloned the sublist because sublist() only returns a view of the list list1, and that's not what you want here.
Your class Example can implement "Comparable" so that you can define how they need to be compared. You will need to implement the method compareTo(). Something like this:
public class Example implements Comparable<Example> {
private int integerVal = <a value>;
public int compareTo(Example exampleObject) {
return exampleObject.integerVal - this.integerVal;
}
}
Have a look at this link, more precisely the class that begins as follows:
public class Fruit implements Comparable<Fruit>{
If you want to sort your objects...
Example e;
int min=-1; // assuming the list has +ve numbers only
for (Example elem : yourList)
{
if ( elem.gtVaribale() <= min ) //assuming you have variable field in your object
{
e = elem;
min = elem.getVariable();
}
}
yourList.remove(e);
//repeat this for remaining elements of the list
//you can create another sorted list, and do sortedList.add(e), so that sortedList
//have objects in ascending order (of the variable you want to sort) of objects you had in yourList
This is just a pseudoCode and I have not compiled it.
Here you will have to override the comparable method for class Example.
You have to let compiler know which way it should compare your e variable to its list's elements so as to remove it.

INTERSECT result of 2 ArrayList containing Integer values

I've two ArrayList both containing Integer values. My objective is to get identical/common/duplicate values comparing these 2 list. In other words (in SQL parlance), I need the INTERSECT result of two lists, that is, values that appear in both list.
Example:
ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(100);
list1.add(200);
list1.add(300);
list1.add(400);
list1.add(500);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(300);
list2.add(600);
One kind of implementation/solution I could think along is looping one of the list something like:
ArrayList<Integer> intersectList = new ArrayList<Integer>();
for (Integer intValue : list1)
{
if(list2.contains(intValue))
intersectList.add(intValue);
}
In this case, intersectList would contain only 1 Integer item being added, that is 300, which appears in both list.
My question is, are there any better/fastest/efficient way of implementing this logic? Any options available in Apache Commons library?. Any other ideas/suggestions/comments are appreciated.
NOTE: For illustration purpose, I've just shown here 5 items and 2 items being added into the list. In my real-time implementation, there will be more than 1000 elements in each list. Therefore, performance is also a key factor to be considered.
If you're okay with overwriting result for list1:
list1.retainAll(list2);
otherwise clone/copy list1 first.
Not sure on performance though.
list1.retainAll(list2)//for intersection
Use ListUtils from org.apache.commons.collections if you do not want to modify existing list.
ListUtils.intersection(list1, list2)

Count the occurrences of items in ArrayList

I have a java.util.ArrayList<Item> and an Item object.
Now, I want to obtain the number of times the Item is stored in the arraylist.
I know that I can do arrayList.contains() check but it returns true, irrespective of whether it contains one or more Items.
Q1. How can I find the number of time the Item is stored in the list?
Q2. Also, If the list contains more than one Item, then how can I determine the index of other Items because arrayList.indexOf(item) returns the index of only first Item every time?
You can use Collections class:
public static int frequency(Collection<?> c, Object o)
Returns the number of elements in the specified collection equal to the specified object. More formally, returns the number of elements e in the collection such that (o == null ? e == null : o.equals(e)).
If you need to count occurencies of a long list many times I suggest you to use an HashMap to store the counters and update them while you insert new items to the list. This would avoid calculating any kind of counters.. but of course you won't have indices.
HashMap<Item, Integer> counters = new HashMap<Item, Integer>(5000);
ArrayList<Item> items = new ArrayList<Item>(5000);
void insert(Item newEl)
{
if (counters.contains(newEl))
counters.put(newEl, counters.get(newEl)+1);
else
counters.put(newEl, 1);
items.add(newEl);
}
A final hint: you can use other collections framework (like Apache Collections) and use a Bag datastructure that is described as
Defines a collection that counts the number of times an object appears in the collection.
So exactly what you need..
This is easy to do by hand.
public int countNumberEqual(ArrayList<Item> itemList, Item itemToCheck) {
int count = 0;
for (Item i : itemList) {
if (i.equals(itemToCheck)) {
count++;
}
}
return count;
}
Keep in mind that if you don't override equals in your Item class, this method will use object identity (as this is the implementation of Object.equals()).
Edit: Regarding your second question (please try to limit posts to one question apiece), you can do this by hand as well.
public List<Integer> indices(ArrayList<Item> items, Item itemToCheck) {
ArrayList<Integer> ret = new ArrayList<Integer>();
for (int i = 0; i < items.size(); i++) {
if (items.get(i).equals(itemToCheck)) {
ret.add(i);
}
}
return ret;
}
As the other respondents have already said, if you're firmly committed to storing your items in an unordered ArrayList, then counting items will take O(n) time, where n is the number of items in the list. Here at SO, we give advice but we don't do magic!
As I just hinted, if the list gets searched a lot more than it's modified, it might make sense to keep it sorted. If your list is sorted then you can find your item in O(log n) time, which is a lot quicker; and if you have a hashcode implementation that goes well with your equals, all the identical items will be right next to each other.
Another possibility would be to create and maintain two data structures in parallel. You could use a HashMap containing your items as keys and their count as values. You'd be obligated to update this second structure any time your list changes, but item count lookups would be o(1).
I could be wrong, but it seems to me like the data structure you actually want might be a Multiset (from google-collections/guava) rather than a List. It allows multiples, unlike Set, but doesn't actually care about the order. Given that, it has a int count(Object element) method that does exactly what you want. And since it isn't a list and has implementations backed by a HashMap, getting the count is considerably more efficient.
Thanks for your all nice suggestion. But this below code is really very useful as we dont have any search method with List that can give number of occurance.
void insert(Item newEl)
{
if (counters.contains(newEl))
counters.put(newEl, counters.get(newEl)+1);
else
counters.put(newEl, 1);
items.add(newEl);
}
Thanks to Jack. Good posting.
Thanks,
Binod Suman
http://binodsuman.blogspot.com
I know this is an old post, but since I did not see a hash map solution, I decided to add a pseudo code on hash-map for anyone that needs it in the future. Assuming arraylist and Float data types.
Map<Float,Float> hm = new HashMap<>();
for(float k : Arralistentry) {
Float j = hm.get(k);
hm.put(k,(j==null ? 1 : j+1));
}
for(Map.Entry<Float, Float> value : hm.entrySet()) {
System.out.println("\n" +value.getKey()+" occurs : "+value.getValue()+" times");
}

Categories