I have two sorted linked list l1 and l2. I wanted to merge l2 into l1 while keeping l1 sorted. My return statement is l1 sorted and l2 is an empty list. How do I approach this problem by using insert_before, insert_after, and remove_node function? Any ideas?
If you know how linked lists are implemented, you can easily just iterate through both of them, using something like the approach below. If you don't know too much about linked lists you might want to read up on those first.
if(l1 == null || l2 == null){
return l1==null ? l2 : l1;
indexA = indexB = 0;
elemA = l1.get(0);
elemB = l2.get(0);
while(indexA<l1.size() || indexB<l2.size()){
if(indexA==l1.size()){
l1.insert_after(l1.size()-1,elemB);
indexA++;
indexB++;
if(indexB<l2.size()){
elemB = l2.get(indexB);
}
continue;
}
if(indexB==l2.size()){
break;
}
if(elemA<elemB){
indexA++;
if(indexA<l1.size()){
elemA = l1.get(indexA);
}
continue;
}
if(elemA>elemB){
l1.insert_before(indexA,elemB);
indexA++;
indexB++;
if(indexB<l2.size()){
elemB = l2.get(indexB);
}
}
return l1;
this is a somehow java like implementation, it iterates through both lists and merges them together on the go. I decided to only return l1 as the empty list would be somewhat useless right?, all the inefficient get() calls could be avoided by writing an own simple LinkedList class to gain access to the next and last fields, which would greatly facilitate navigation.
If you could provide additional information about the methods you have available or the language this has to be written in I could probably provide you with better explanations.
Edit: Explanation
first both elemA /elemB are given the value of the first element in the linked lists then the while loop is used to iterate through them until the index values that are used to keep track of where we are in the lists are both too high (e.g. ==size of list)
Now the first two if statements are to check wheter one of the lists is already completely iterated through, if this is the case for the first list, the next element of the second list is just added behind the last element of l1, as it must be greater than it, otherwise indexA would not have been increased. (In this if statement indexA is also incremented because the size of the list is getting bigger and indexA is compared to l1.size() ), finally the continue statement skips to the next iteration of the loop.
The second if statement in the while loop tests if the second list has already completely been iterated through, if this is true there is nothing more to merge so the loop is stopped by the break statement.
below that is more or less classic mergesort;
if the current element of l1 is smaller than the current element of l2, just go to the next element of l1 and go to next iteration of loop, otherwise insert the current element of l2 before elemA and iterate further here indexA is also incremented because otherwise it would not point to the right element anymore as an element was inserted before it.
is this sufficient?
Edit: Added testing if either of the lists is null as suggested by #itwasntme
The functions insert_before, insert_after, and remove_node are not clearly defined in the question. So assuming one of the parameters is a reference to the "list", is the other parameter an index, an iterator, or a pointer to a node? If the lists are doubly linked lists, then it makes sense for the second parameter to be an iterator or a pointer to a node (each node has a pointer to previous node, so there's no need to scan according to an index to find the prior node).
In the case of Visual Studio's std::list::sort, it uses iterators and std::list::splice to move nodes within a list, using iterators to track the beginning and ending of sub-lists during a merge sort. The version of std::list::splice used by std::list::sort combines remove_node and insert_before into a single function.
Related
I'm new to the data structures and recursion concept. I'm struggling to understand why and who he was able to use the recursion in this concept. I found this code in the forums for this and I couldn't really understand the concept of this. For simple case of 2 1 3 4, if any one can explain the iteration steps, it will be greatly appreciated on my behalf.
Here is the link for hacker rank:
https://www.hackerrank.com/challenges/insert-a-node-into-a-sorted-doubly-linked-list
Node SortedInsert(Node head,int data) {
Node n = new Node();
n.data = data;
if (head == null) {
return n;
}
else if (data <= head.data) {
n.next = head;
head.prev = n;
return n;
}
else {
Node rest = SortedInsert(head.next, data);
head.next = rest;
rest.prev = head;
return head;
}
}
Recursion:
Recursion means a function calls itself. It is used as a simple way to save state information for algorithms that require saving of multiple states, usually a large number of states, and retrieving them in reverse order. (There are alternative techniques that are more professional and less prone to memory issues, such as using a Stack object to save program state).
This example is poor but typical of intro to recursion. Yes, you can iterate through a linked list using recursion but there is absolutely no reason to. A loop would be more appropriate. This is purely for demonstrating how recursion works. So, to answer your question "Why?" it is simply so you can learn the concept and use it later in other algorithms that it actually makes sense.
Recursion is useful when instead of a linked list you have a tree, where each node points to multiple other nodes. In that case, you need to save your state (which node you are on, and which subnode you called last) so that you can traversing one of the linked nodes, then return and go to the next node.
You also asked "how". When a function calls itself, all of its variables are saved (on the program stack) and new ones are created for the next iteration of itself. Then, when that call returns, it goes back to where it was called from and the previous set of variables are loaded. This is very different from a "jump" or a loop of some kind, where the same copies of the variables are used each time. By using recursion, there is a new copy of every local variable each time it is called. This is true even of the "data" variable in the example, which never changes (hence, one inefficiency).
We're learning about hash tables in my data structures and algorithms class, and I'm having trouble understanding separate chaining.
I know the basic premise: each bucket has a pointer to a Node that contains a key-value pair, and each Node contains a pointer to the next (potential) Node in the current bucket's mini linked list. This is mainly used to handle collisions.
Now, suppose for simplicity that the hash table has 5 buckets. Suppose I wrote the following lines of code in my main after creating an appropriate hash table instance.
myHashTable["rick"] = "Rick Sanchez";
myHashTable["morty"] = "Morty Smith";
Let's imagine whatever hashing function we're using just so happens to produce the same bucket index for both string keys rick and morty. Let's say that bucket index is index 0, for simplicity.
So at index 0 in our hash table, we have two nodes with values of Rick Sanchez and Morty Smith, in whatever order we decide to put them in (the first pointing to the second).
When I want to display the corresponding value for rick, which is Rick Sanchez per our code here, the hashing function will produce the bucket index of 0.
How do I decide which node needs to be returned? Do I loop through the nodes until I find the one whose key matches rick?
To resolve Hash Tables conflicts, that's it, to put or get an item into the Hash Table whose hash value collides with another one, you will end up reducing a map to the data structure that is backing the hash table implementation; this is generally a linked list. In the case of a collision this is the worst case for the Hash Table structure and you will end up with an O(n) operation to get to the correct item in the linked list. That's it, a loop as you said, that will search the item with the matching key. But, in the cases that you have a data structure like a balanced tree to search, it can be O(logN) time, as the Java8 implementation.
As JEP 180: Handle Frequent HashMap Collisions with Balanced Trees says:
The principal idea is that once the number of items in a hash bucket
grows beyond a certain threshold, that bucket will switch from using a
linked list of entries to a balanced tree. In the case of high hash
collisions, this will improve worst-case performance from O(n) to
O(log n).
This technique has already been implemented in the latest version of
the java.util.concurrent.ConcurrentHashMap class, which is also slated
for inclusion in JDK 8 as part of JEP 155. Portions of that code will
be re-used to implement the same idea in the HashMap and LinkedHashMap
classes.
I strongly suggest to always look at some existing implementation. To say about one, you could look at the Java 7 implementation. That will increase your code reading skills, that is almost more important or you do more often than writing code. I know that it is more effort but it will pay off.
For example, take a look at the HashTable.get method from Java 7:
public synchronized V get(Object key) {
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return (V)e.value;
}
}
return null;
}
Here we see that if ((e.hash == hash) && e.key.equals(key)) is trying to find the correct item with the matching key.
And here is the full source code: HashTable.java
I have the following pseudo-code:
function X(data, limit, level = 0)
{
result = [];
foreach (Y(data, level) as entity) {
if (level < limit) {
result = result + X(entity, limit, level + 1);
} else {
//trivial recursion case:
result = result + Z(entity);
}
}
return result;
}
which I need to turn into a plain (e.g. without recursive calls). So far I'm out of ideas regarding how to do that elegantly. Following this answer I see that I must construct the entire stack frames which are basically the code repetitions (i.e. I will place same code again and again with different return addresses).
Or I tried stuff like these suggestions - where there is a phrase
Find a recursive call that’s not a tail call.
Identify what work is being done between that call and its return statement.
But I do not understand how can the "work" be identified in the case when it is happening from within internal loop.
So, my problem is that all examples above are providing cases when the "work can be easily identified" because there are no control instructions from within the function. I understand the concept behind recursion on a compilation level, but what I want to avoid is code repetition. So,
My question: how to approach transformation of the pseudo-code above which does not mean code repetitions for simulating stack frames?
It looks like an algorithm to descend a nested data structure (lists of lists) and flatten it out into a single list. It would have been good to have a simple description like that in the question.
To do that, you need to keep track of multiple indices / iterators / cursors, one at each level that you've descended through. A recursive implementation does that by using the call stack. A non-recursive implementation will need a manually-implemented stack data structure where you can push/pop stuff.
Since you don't have to save context (registers) and a return address on the call stack, just the actual iterator (e.g. array index), this can be a lot more space efficient.
When you're looping over the result of Y and need to call X or Z, push the current state onto the stack. Branch back to the beginning of the foreach, and call Y on the new entity. When you get to the end of a loop, pop the old state if there is any, and pick up in the middle of that loop.
There is a stream of random characters coming like 'a''b''c''a'... and so on. At any given point in time when I query I need to get the first non repeating character. For example, for the input "abca", 'b' should be returned since a is repeated and the first non repeating character is 'b'.
There needs to be two methods, one for inserting and one for querying.
My solution is to have a linkedList to store the incoming stream characters. While I get the next character, I just compare with all the current characters and if present I will not insert into the end of linkedlist, else I will insert at the end. By this approach, the query will take O(1) since I will get the first element on the linkedlist and insert will take O(n) since I need to compare from the first element till the last element in the worst case.
Is there any better performing way?
Either you haven't explained your algorithm well or it won't return the correct result. In the example a b a, would your algorithm return a (because it is the first element in the linked list)?
Anyway, here is a modification that improves performance. The idea is to use a hash map from characters to (doubly) linked list nodes. This map can be used to determine if a character has already been inserted and to get to the required node quickly. We should allow a null value for the map target (instead of the list node) to express a character that has ocurred more than once already.
The insertion method works as follows:
Check if the map contains the current character (O(1)). If not, add it to the end of the list and add a reference to the map (O(1)).
If the character is already in the map: Check if the pointed to node is null (O(1)). If so, just ignore it. If it is not, remove the pointed to node from the list and update the reference to a null value (O(1)).
Overall, a O(1) operation.
The query works as in your previous solution.
Here is a C# implementation. It's basically a 1:1 translation of the above explanation:
class StreamAnalyzer
{
LinkedList<char> characterList = new LinkedList<char>();
Dictionary<char, LinkedListNode<char>> characterMap
= new Dictionary<char, LinkedListNode<char>>();
public void AddCharacter(char c)
{
LinkedListNode<char> referencedNode;
if (characterMap.TryGetValue(c, out referencedNode))
{
if(referencedNode != null)
{
characterList.Remove(referencedNode);
characterMap[c] = null;
}
}
else
{
var node = new LinkedListNode<char>(c);
characterList.AddLast(node);
characterMap.Add(c, node);
}
}
public char? GetFirstNonRepeatingCharacter()
{
if (characterList.First == null)
return null;
else
return characterList.First.Value;
}
}
Need to know is there a way to count the frequency of items in a array without using two loops. This is without knowing the size of the array. If I know the size of the array I can use switch without looping. But I need more versatile than that. I think modifying the quicksort may give better results.
Array[n];
TwoDArray[n][2];
First loop will go on Array[], while second loop is to find the element and increase it count in two-d array.
max = 0;
for(int i=0;i<Array.length;i++){
found= false;
for(int j=0;j<TwoDArray[max].length;j++){
if(TwoDArray[j][0]==Array[i]){
TwoDArray[j][1]+=;
found = true;
break;
}
}
if(found==false){
TwoDArray[max+1][0]=Array[i];
TwoDArray[max+1][1]=1;
max+=;
}
If you can comment or provide better solution would be very helpful.
Use map or hash table to implement this. Insert key as the array item and value as the frequency.
Alternatively you can use array too if the range of array elements are not too large. Increase the count of value at indexes corresponding to the array element.
I would build a map keyed by the item in the array and with a value that is the count of that item. One pass over the array to build the map that contains the counts. For each item, look it's count up in the map, increment the count, and put the new count back into the map.
The map put and get operations can be constant time (e.g., if you use a hash map implementation with a good hash function and properly sized backing store). This means you can compute the frequencies in time proportional to the number of elements in your array.
I'm not saying this is better than using a map or hash table (especially not when there are lots of duplicates, though in that case you can get close to O(n) sorting with certain techniques, so this is not too bad either), it's just an alternative.
Sort the array
Use a (single) for-loop to iterate through the sorted array
If you find the same element as the previous one, increment the current count
If you find a different element, store the previous element and its count and set the count to 1
At the end of the loop, store the previous element and its count