Merge two sorted linked lists in java - java

I need to merge two sorted linked list into one sorted list. I've been trying to do so for hours, but when I reach the end of one of the list I always have some trouble. This is the best I could do. My filaA and filaB are liked lists of data type "long".
LinkedList<Long> result= new LinkedList<Long>();
iterA = filaA.listIterator();
iterB = filaB.listIterator();
while (iterA.hasNext() && iterB.hasNext()) {
n = iterA.next();
m = iterB.next();
if (n <= m) {
filafusion.add(n);
n = iterA.next();
} else {
filafusion.add(m);
m = iterB.next();
}
}
if (iterA.hasNext()) {
while (iterA.hasNext()) {
filafusion.add(iterA.next());
}
} else {
while (iterB.hasNext()) {
filafusion.add(iterB.next());
}
}
iterfusion = filafusion.listIterator();
while (iterfusion.hasNext()) {
System.out.print(iterfusion.next());
}
}
The general idea here is to compare one by one and then move the iterator to the next. But they are moving at the same time, so I'm only comparing first with first, second with second, and so on.
I also tried to move the n = iterA.next();m = iterB.next(); before the while loop, which makes it work much better, but then I don't know which list runs out of elements. Only works if the lists are the same lenght but then one of the elements won't enter the result.
I've seen many codes for this here, but they all use Nodes and recursion and stuff I'm not familiar with. I think using iterators will make it more efficient, but that's what's got me so confused, I'm not iterating where I should :(
Any suggestions will be appreciated.

You can use the standard java.util.TreeSet to do the job.
here is a full example :
LinkedList<Long> filaA = new LinkedList<>();
filaA.add(1l);
filaA.add(3l);
filaA.add(5l);
LinkedList<Long> filaB = new LinkedList<>();
filaB.add(2l);
filaB.add(4l);
filaB.add(6l);
Set<Long> result = new TreeSet<>();
result.addAll(filaA);
result.addAll(filaB);
System.out.println(result);
TreeSet use natural order.

I just adapted your code. If you are able to use Java 8, then I have a much shorter solution below.
Iterator iterA = filaA.listIterator();
Iterator iterB = filaB.listIterator();
Long n = (Long)iterA.next();
Long m = (Long)iterB.next();
while (true) {
if (n <= m) {
filafusion.add(n);
if(iterA.hasNext()){
n = (Long)iterA.next();
}
else{
filafusion.add(m);
while(iterB.hasNext()){
filafusion.add((Long)iterB.next());
}
break;
}
} else {
filafusion.add(m);
if(iterB.hasNext()){
m = (Long)iterB.next();
}
else{
filafusion.add(n);
while(iterA.hasNext()){
filafusion.add((Long)iterA.next());
}
break;
}
}
}
Iterator iterfusion = filafusion.listIterator();
while (iterfusion.hasNext()) {
System.out.println(iterfusion.next());
}
Here is the Java 8 way to do it. And it also works for unsorted input lists:
Stream stream = Stream.concat(filaA.stream(), filaB.stream());
stream.sorted().forEach(System.out::println);

public static <T extends Comparable<T>> List<T> mergeSortedLists(List<T> list1, List<T> list2) {
List<T> result = new ArrayList<>();
Iterator<T> iterator1 = list1.iterator();
Iterator<T> iterator2 = list2.iterator();
boolean hasNext1 = iterator1.hasNext();
boolean hasNext2 = iterator2.hasNext();
T next1 = hasNext1 ? iterator1.next() : null;
T next2 = hasNext2 ? iterator2.next() : null;
while (hasNext1 || hasNext2) {
if (!hasNext1) {
result.add(next2);
hasNext2 = iterator2.hasNext();
next2 = hasNext2 ? iterator2.next() : null;
} else if (!hasNext2) {
result.add(next1);
hasNext1 = iterator1.hasNext();
next1 = hasNext1 ? iterator1.next() : null;
} else {
if (next1.compareTo(next2) < 0) {
result.add(next1);
hasNext1 = iterator1.hasNext();
next1 = hasNext1 ? iterator1.next() : null;
} else {
result.add(next2);
hasNext2 = iterator2.hasNext();
next2 = hasNext2 ? iterator2.next() : null;
}
}
}
return result;
}

Related

How to set two Java Arraylist values into one Java object?

I have an issue while working with java ArrayList. Here is the brief description:
By making a web service call, I will get all the videos around 900+ as Java objects. These Java objects are lacking some of the required information. So I am again making a call to another web service by passing the video id. This also returns Java objects.
I am storing the first web service call values and the second web service call values into two different Java ArrayLists as below:
List mediaList = new ArrayList();
List mediaVOs = new ArrayList();
Finally I am writing a method by passing two lists and setting those values into one java object. This should return the total objects around 942. But this is returning some odd number 887364 instead of 942 count.
Please help me resolving the issue. Here is the code:
client = getClient();
if (client != null) {
List<MediaEntry> mediaList = getAllMedia();
if (mediaList.size() >= 1) {
System.out.println("Total Media ------>" + mediaList.size());
MetadataListResponse metadataListResponse = null;
Media mediaVO = null;
List<List<String>> metadataValues = new ArrayList<List<String>>();
List<String> categoriesList = new ArrayList<String>();
List<String> accountNamesList = new ArrayList<String>();
List<String> ownerNamesList = new ArrayList<String>();
List<String> countryList = new ArrayList<String>();
List<String> languageList = new ArrayList<String>();
for(MediaEntry entry:mediaList) {
if(entry != null) {
metadataListResponse = getMetadata(entry.id);
if (metadataListResponse.totalCount >= 1) {
mediaVO = new Media();
List<Metadata> metadataObjs = metadataListResponse.objects;
if (metadataObjs != null
&& metadataObjs.size() > 0) {
for (int i = 0; i < metadataObjs.size(); i++) {
Metadata metadata = metadataObjs
.get(i);
if (metadata != null) {
if (metadata.xml != null) {
metadataValues = parseXml(metadata.xml);
if (metadataValues.size() != 0) {
categoriesList = metadataValues
.get(0);
accountNamesList = metadataValues.get(1);
ownerNamesList = metadataValues.get(2);
countryList = metadataValues.get(3);
languageList = metadataValues.get(4);
if (categoriesList.size() == 1) {
for (String categoryName : categoriesList) {
//System.out
//.println("categoryName"+categoryName);
mediaVO.setCategories(categoryName);
}
}
if (accountNamesList.size() == 1) {
for (String accountName : accountNamesList) {
//System.out
//.println("accountName"+accountName);
mediaVO.setAccountName(accountName);
}
}
if (ownerNamesList.size() == 1) {
for (String ownerName : ownerNamesList) {
//System.out
//.println("ownerName"+ownerName);
mediaVO.setOwnerName(ownerName);
}
}
if (countryList.size() == 1) {
for (String country : countryList) {
//System.out
//.println("country"+country);
mediaVO.setCountry(country);
}
}
if (languageList.size() == 1) {
for (String language : languageList) {
//System.out
//.println("language"+language);
mediaVO.setLanguage(language);
}
}
}
}
}
}
}
}
mediaVOs.add(mediaVO);
}
}
System.out.println("mediaVOs.size()------>"+mediaVOs.size());
List<Media> medias = setMediaVO(mediaList, mediaVOs);
if(medias.size() >= 1) {
System.out.println("Final medias size ------>"+medias.size());
mediaXml = convertToXml(medias);
System.out.println("Final Media XML converted ------->"+mediaXml);
Document doc = convertStrToDoc(mediaXml);
}
}
}
private List<Media> setMediaVO(List<MediaEntry> mediaList,List<Media> mediaList1) {
if(mediaList.size() >= 1) {
if(mediaList1.size() >= 1) {
for(MediaEntry media:mediaList) {
for(Media media1:mediaList1) {
Media mediaVO = new Media();
MediaType mediaType = media.mediaType;
mediaVO.setMediaId(media.id);
mediaVO.setMediaName(media.name);
mediaVO.setMediaDesc(media.description);
mediaVO.setCreatedDate(media.createdAt);
mediaVO.setCreditUserName(media.creditUserName);
mediaVO.setDataUrl(media.dataUrl);
mediaVO.setDownloadUrl(media.dataUrl);
mediaVO.setDuration(media.duration);
mediaVO.setEndDate(media.endDate);
mediaVO.setEntitledUsersEdit(media.entitledUsersEdit);
mediaVO.setEntitledUsersPublish(media.entitledUsersPublish);
mediaVO.setLastPlayedAt(media.lastPlayedAt);
mediaVO.setMediaType(mediaType.toString());
mediaVO.setUpdatedDate(media.updatedAt);
mediaVO.setPlays(media.plays);
mediaVO.setViews(media.views);
mediaVO.setCategories(media1.getCategories());
mediaVO.setAccountName(media1.getAccountName());
mediaVO.setOwnerName(media1.getOwnerName());
mediaVO.setCountry(media1.getCountry());
mediaVO.setLanguage(media1.getLanguage());
medias.add(mediaVO);
}
}
}
}
return medias;
}
Thanks,
Raji
Your problem is here :
for(MediaEntry media:mediaList) {
for(Media media1:mediaList1) {
For each MediaEntry, you're looping on each Media, which means you'll execute the code inside 942 * 942 times, while what you want is to execute it 942 times. You've got to match MediaEntries with Media and execute the code once.
Let me try to explain this in a way where everybody understands what i mean.
The problem is indeed the fact that you multiply 942 by itself.
This happens cause of the following code:
private List<Media> setMediaVO(List<MediaEntry> mediaList,List<Media> mediaList1) {
if(mediaList.size() >= 1) {
if(mediaList1.size() >= 1) {
for(MediaEntry media:mediaList) {
for(Media media1:mediaList1) {
//Do stuff
}
}
}
}
return medias;
}
Here you loop though medialist 1 for each item in medialist and do stuff with it.
At the end of this code you add each entry found in medialist 1 to a other list but this happend 942 times per item in the first list.
And since that list has 942 items you get the "odd" number of 887.364.

Linked List Optimization

I'm working on this program that emulates restriction enzymes and DNA splicing. I'm using DnaSequenceNode[s] as linked list nodes.
I have a problem with one of the function in my code, cutSplice() is supposed to create a new DnaStrand that is a clone of the current DnaStrand, but with every instance of enzyme replaced by splicee.
For example, if the LinkedDnaStrand is instantiated with "TTGATCC", and
cutSplice("GAT", "TTAAGG") is called, then the linked list should become something like (previous pointers not shown):
first -> "TT" -> "TTAAGG" -> "CC" -> null
My function works. However, my method cutSplice() takes more than 80 seconds to splice 200 DNAs. I'm supposed to bring that 80 seconds to 2 seconds.
This is all my code for the class : LinkedDnaStrand.java
And here's the code for the method cutSplice()
public DnaStrand cutSplice(String enzyme, String splicee) {
DnaStrand newStrand = null;
String original_Dna = this.toString();
String new_Dna = original_Dna.replaceAll(enzyme, splicee);
String[] splicee_split = new_Dna.split(splicee); // splits the new DNA string DnaStrand
newStrand = null;
int i = 0;
if (original_Dna.startsWith(enzyme)) {
newStrand = new LinkedDnaStrand(splicee);
} else {
newStrand = new LinkedDnaStrand(splicee_split[0]);
newStrand.append(splicee);
}
for (i = 1; i < splicee_split.length - 1; i++) {
String node = splicee_split[i];
newStrand.append(node);
newStrand.append(splicee);
}
newStrand.append(splicee_split[splicee_split.length - 1]);
if (original_Dna.endsWith(enzyme)) {
newStrand.append(splicee);
}
return newStrand;
}
Does anybody see anything that could make a critical difference on the time this function takes to process 200 DNAs sample?
Well, it is comfortable to use the string methods, but you are losing time in converting to the string, back to sequence, and (as pointed out in the previous comments) with the regex based string functions.
It will certainly consume less time to operate on the linked list directly, although this will require you to implement the replacement algorithm yourself:
#Override
public LinkedDnaStrand cutSplice(String enzyme, String splicee)
{
LinkedDnaStrand strand = new LinkedDnaStrand();
DnaSequenceNode end = null;
DnaSequenceNode begin = top;
int pos = 0;
DnaSequenceNode tmpStart, tmpEnd;
for (DnaSequenceNode current = top; current != null; current = current.next)
{
if(current.value != enzyme.charAt(pos))
{
tmpStart = tmpEnd = new DnaSequenceNode(begin.value);
for (DnaSequenceNode n = begin.next; n != current.next; n = n.next)
{
DnaSequenceNode c = new DnaSequenceNode(n.value);
tmpEnd.next = c;
c.previous = tmpEnd;
tmpEnd = c;
}
}
else if(++pos == enzyme.length())
{
tmpStart = tmpEnd = new DnaSequenceNode(splicee.charAt(0));
for (int i = 1; i < splicee.length(); ++i)
{
DnaSequenceNode c = new DnaSequenceNode(splicee.charAt(i));
tmpEnd.next = c;
c.previous = tmpEnd;
tmpEnd = c;
}
}
else
{
continue;
}
if(end == null)
{
strand.top = end = tmpStart;
}
else
{
end.next = tmpStart;
tmpStart.previous = end;
}
end = tmpEnd;
begin = current.next;
pos = 0;
}
return strand;
}
I do not claim that there is not any opportunity to further optimize, but this should be a lot faster as the original version. I tested it successfully with the example you gave, if you yet find a bug, feel free to fix it yourself...
Note 1: I did explicitely create a new sequence from the string (instead of using the constructor) to get the end of the sequence without having to iterate over it again.
Note 2: I assumed existing a constructor DnaSequenceNode(char value) and DnaSequenceNode having a member public char value. You might have to adjust the code appropriately if any of these assumptions fails.

Add the items from one list to another list in java

I have two arraylists say
ArrayList<BaseItem> normal;
ArrayList<BaseItem> highlighted;
normal = new ArrayList<BaseItem>();
highlighted = new ArrayList<BaseItem>();
what I am doing is I am Iterating through a 3rd list(called MyItems) and adding the items in it called highlight and normal to the above two lists like this.
for (Iterator<BaseItem> iterator = MyItems.iterator(); iterator.hasNext();) {
BaseItem itemtype = iterator.next();
if (itemtype.isHighlight()) {
highlighted.add(itemtype);
}
else{
normal.add(itemtype);
}
}
So my question is I want to add every 5th and 6th item of the highlited list to the list called normal .i.e elements like 5,6,11,12,17,18 and so on
and also I want to add every 6th and 7th item of normal list to highlighted list i.e 6,7,13,14 and so on.
so now my highlighted and normal lists will contain the items like this
Highlighted -> highlighted1,highlighted2,highlighted3,highlighted4,normal6,normal7 highlighted7,highlighted8.highlighted9,highlighted10,normal13,normal14 and so on
Normal -> Noraml1,normal2,normal3,normal4,normal5,highlighted5,highlighted6,normal7,normal8,normal9,normal10,normal11,normal12,highlighted11,highlighted12 and so on
Any help is always appreciated,
Thanks
If I understand, use a counter when after 5 and 6 insert in your list, add in normal list instead of highlighted list
Try this:
int highAdded = 0;
int normalAdded = 0;
for (Iterator<BaseItem> iterator = MyItems.iterator(); iterator.hasNext();) {
BaseItem itemtype = iterator.next();
if (itemtype.isHighlight()) {
highAdded++;
if (highAdded == 5) {
normal.add(itemtype);
} else if (highAdded == 6) {
normal.add(itemtype);
highAdded = 0;
} else {
highlighted.add(itemtype);
}
}
else{
normalAdded++;
if (normalAdded == 6) {
highlighted.add(itemtype);
} else if (normalAdded == 7) {
highlighted.add(itemtype);
normalAdded = 0;
} else {
normal.add(itemtype);
}
}
}
EDIT
I write this code:
public class StackOverFlowSample {
public static void main(String [] args) {
List<String> lst = new ArrayList<String>();
List<String> lstHigh = new ArrayList<String>();
List<String> lstNormal = new ArrayList<String>();
lst.add("highlighted01");
lst.add("highlighted02");
lst.add("highlighted03");
lst.add("highlighted04");
lst.add("highlighted05");
lst.add("highlighted06");
lst.add("highlighted07");
lst.add("highlighted08");
lst.add("highlighted09");
lst.add("highlighted10");
lst.add("highlighted11");
lst.add("highlighted12");
lst.add("highlighted13");
lst.add("highlighted14");
lst.add("highlighted15");
lst.add("highlighted16");
lst.add("normal01");
lst.add("normal02");
lst.add("normal03");
lst.add("normal04");
lst.add("normal05");
lst.add("normal06");
lst.add("normal07");
lst.add("normal08");
lst.add("normal09");
lst.add("normal10");
lst.add("normal11");
lst.add("normal12");
lst.add("normal13");
lst.add("normal14");
lst.add("normal15");
lst.add("normal16");
int highAdded = 0;
int normalAdded = 0;
for (Iterator<String> iterator = lst.iterator(); iterator.hasNext();) {
String itemtype = iterator.next();
if (itemtype.startsWith("highlighted")) {
highAdded++;
if (highAdded == 5) {
lstNormal.add(itemtype);
} else if (highAdded == 6) {
lstNormal.add(itemtype);
highAdded = 0;
} else {
lstHigh.add(itemtype);
}
}
else{
normalAdded++;
if (normalAdded == 6) {
lstHigh.add(itemtype);
} else if (normalAdded == 7) {
lstHigh.add(itemtype);
normalAdded = 0;
} else {
lstNormal.add(itemtype);
}
}
}
String result = "HIGHLIGHTED ARRAY: ";
for (String curr : lstHigh) {
result += curr + ", ";
}
System.out.print(result);
result = "NORMAL ARRAY: ";
for (String curr : lstNormal) {
result += curr + ", ";
}
System.out.print(result);
}
}
The output is:
HIGHLIGHTED ARRAY: highlighted01, highlighted02, highlighted03, highlighted04, highlighted07, highlighted08, highlighted09, highlighted10, highlighted13, highlighted14, highlighted15, highlighted16, normal06, normal07, normal13, normal14,
NORMAL ARRAY: highlighted05, highlighted06, highlighted11, highlighted12, normal01, normal02, normal03, normal04, normal05, normal08, normal09, normal10, normal11, normal12, normal15, normal16,
Tell me if it's OK ;)

In java How to merge two different size arraylist and make a new Arraylist?

I have two arraylist name preBusinessList, businessList. In business List I have data from server, and in preBusinessList is the local one. In lists I have id, count value Betterly demonstrate as below
Now I wanted to make a newBusinessList like this
How can I do it in java, please help me to solve this
Then I would use a map to do the merge using id as the key and convert it back to your list of (id,value) pairs
You can use:
Collections.sort(new ArrayList<...>(preBusinessList).addAll(businessList), comparator)
Where comparator is a class that implements Comparator interface (will be responsible for sorting as you wish)
assumming i understood your problem correctly (big if...):
also, i assume each element in the lists is a Pair - as it looks from your data (just a dumb wrapper class that holds 2 integers). if its some other class you'll need to adjust this code.
private Map<Integer,Integer> finalValues = new HashMap<Integer,Integer>();
for (Pair<Integer,Integer> entry : preBusinessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
//2nd list overwrites values from 1st (anything not overwritten remains)
for (Pair<Integer,Integer> entry : businessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
ArrayList<Pair<Integer,Integer>> finalList = new ArrayList<>();
for (Map.Entry<Integer,Integer> entry : finalValues) {
finalList.add(new Pair(entry.getKey(), entry.getValue());
}
//and now sort the list
Collections.sort(finalList, new Comparator<Pair<Integer,Integer>> {
int compare(Pair<Integer,Integer> a, Pair<Integer,Integer>b) {
return a.getFirst.compareTo(b.getFirst()); //compare by 1st number in pair only
}
});
Assuming something like:
public class Info {
public int id;
public int info;
}
You could merge them on the basis of wanting the keep the one with higher info field as follows:
// Assumes:
// - that the ArrayLists are sorted to have id in order going up
// - no repeated ids in a or in b (but same id can be in both a and b)
ArrayList<Info> merge(ArrayList<Info> a, ArrayList<Info> b) {
int aLength = a.size();
int bLength = b.size();
int ai = 0;
int bi = 0;
ArrayList<Info> result = new ArrayList<Info>();
while ((ai < aLength) && (bi < bLength))
Info aInfo = a.get(ai);
Info bInfo = b.get(bi);
if (aInfo.id == bInfo.id) {
if (aInfo.info >= bInfo.info) result.add(aInfo);
else result.add(bInfo);
ai++;
bi++;
}
else if (aInfo.id < bInfo.id) {
result.add(aInfo);
ai++;
}
else {
result.add(bInfo);
bi++;
}
}
// Add the remaining terms - only one of the loops will actually do anything
for (; ai<aiLength; ai++) {
result.add(a.get(ai));
}
for (; bi<biLength; bi++) {
result.add(b.get(bi));
}
}
Pseudocode :
Iterate over preBusinessList.
Fetch key and see if this key(1,2,3,4,5,6) exists in businesslist
If yes conitnue
Else If no, then add it to businesslist
for(Map.Entry<Integer, Integer> keyValue : preBusinessList.entrySet()) {
if(!businesslist.containsKey(keyValue.getKey())) {
businesslist.put(keyValue.getKey(), keyValue.getValue());
}
}
Updated Answer as per new requirements
boolean ifExists = false;
for(PlaceItems itemPreBusinessList : preBusinessList) {
ifExists = false;
for(PlaceItems itemBusinessList : businessList) {
if(itemBusinessList.businessId == itemPreBusinessList.businessId) {
// Already exists
ifExists = true;
break;
}
}
if(!isExists) {
businessList.add(itemPreBusinessList);
}
}

Java anagram recursion List<List<String>> only storing empty lists<Strings>

Hi In this recursion method i am trying to find all anagrams and add it to a List> but what happens when i run this code is it just returns alot of empty Lists.
private List<List<String>> findAnagrams(LetterInventory words,
ArrayList<String> anagram, int max,
Map<String, LetterInventory> smallDict, int level, List<List<String>> result) {
ArrayList<String> solvedWord = new ArrayList<String>();
LetterInventory shell;
LetterInventory shell2;
if (level < max || max == 0) {
Iterator<String> it = smallDict.keySet().iterator();
while (it.hasNext()) {
String k = it.next();
shell = new LetterInventory(k);
shell2 = words;
if (shell2.subtract(shell) != null) {
anagram.add(k);
shell2 = words.subtract(shell);
if (shell2.isEmpty()) {
//System.out.println(anagram.toString()); it prints off fine here
result.add(anagram); // but doesnt add here
}
else
findAnagrams(shell2, anagram, max, smallDict, level + 1, result);
anagram.remove(anagram.size()-1);
}
}
}
return results;
}
My guess is it's here.
else
findAnagrams(shell2, anagram, max, smallDict, level + 1, result);
anagram.remove(anagram.size()-1); // this is outside of the else case
You remove an element from anagram every time you add it. Did you mean to for it to be in the else?
else {
findAnagrams(shell2, anagram, max, smallDict, level + 1, result);
anagram.remove(anagram.size()-1);
}

Categories

Resources