I have a Chain class that is made of a doubly linked list.
I want to twist two Chains so that every node at even positions will swap with each other. The Chain starts at position 1.
For example, say
this = {1,2,3,4}; //default chain
aChain = {5,6,7,8};
twist(aChain);
Now this would be {1,6,3,8}
and aChain would be {5,2,7,4}
Current Update:
void Chain::twist(Chain & other){
Node* firstOdd1 = this -> head_;
Node* firstOdd2 = other -> head_;
Node* firstEven1 = firstOdd1 -> next;
Node* firstEven2 = firstOdd2 -> next;
for(int i = 0; i < size(); i++){
firstOdd1 -> next = firstEven2;
firstOdd2 -> next = firstEven1;
firstEven1 -> prev = firstOdd2;
firstEven2 -> prev = firstOdd1;
if(firstEven1 -> next != NULL && firstEven2 -> next != NULL){
//updating my pointers for the next iteration
firstOdd1 = firstEven1 -> next;
firstOdd2 = firstEven2 -> next;
firstEven1 = firstOdd1 -> next;
firstEven2 = firstOdd2 -> next;}
else break;
}
}
As you see, I declared 4 pointers so that I don't lose any nodes during my assignments. I also have tail pointers that I need to assign to the last Nodes of both lists after the loop I suppose (if last Nodes are swapped). There's a size() function in the class that return the size of the chain.
This is what I wrote for the iteration step just now.
I left this as a comment, but I might as well make it an answer:
The algorithm is simple: swap the values at every even node in the chain.
No need to start worrying about tails and whatnot, just follow that pattern until you can no longer do it (i.e. you run out of even nodes), then stop and voila, problem solved!
You can clearly see it for the case you submitted:
{1,2,3,4};
{5,6,7,8};
==========
TWISTER
==========
| | |
v v v
{1,6,3,8};
{5,2,7,4};
Another example:
{1,2,3};
{5,6,7,8,9};
==========
TWISTER
==========
| | |
v v v
{1,6,3};
{5,2,7,8,9};
Another one!
{};
{5,6,7,8,9};
==========
TWISTER
==========
| | |
v v v
{};
{5,6,7,8,9};
ONE MORE TIME!
{1};
{5};
==========
TWISTER
==========
| | |
v v v
{1};
{5};
Maybe to help you, create a function which when called with a given node, tells you if it is possible to move it to the next even position.
bool can_move_to_even(Node* node) const {
if (node != nullptr) {
return node->next != nullptr && node->next->next != nullptr
&& node->next != this->_tail && node->next->next != this->_tail;
}
return false;
}
The checks for this->_tail are only for if your this->_tail is not to be considered part of the list, but if it is, then you can safely remove those.
Now what you can do is that if you pass in an even node, it will tell you if that node can reach the next even one or not. Once this function returns false for any of the chains you are twisting, that is when you know it is time to stop.
Be careful of nulls.
Related
Forward Declaration of FindMergePoint()
int FindMergePoint(Node *Larger,int largeCount,Node *Smaller,int SmallCount);
Function which will count the length of both lists the according to the size passes the lists to FindMergePoint() which will return the node of intersection.
int FindMergeNode(Node *headA, Node *headB)
{
Node *PTRA = headA;
Node *PTRB = headB;
int count1 = 0,count2 = 0;
//Count List One
while(PTRA != NULL){
count1++;
PTRA = PTRA->next;
}
//Count List Two
while(PTRB != NULL){
count2++;
PTRB = PTRB->next;
}
//If First list is greater
if(count1 >= count2){
return FindMergePoint(headA,count1,headB,count2);
}
else{//Second is greater
return FindMergePoint(headB,count2,headA,count1);
}
}
Function Which Takes Larger and Smaller Lists and Finds the merge Point
int FindMergePoint(Node *Larger,int largeCount,Node *Smaller,int SmallCount){
Node *PTRL = Larger;
//Now traversing till both lists have same length so then we can move
parallely in both lists
while(largeCount != SmallCount){
PTRL = PTRL->next;
largeCount--;
}
Node *PTRS = Smaller;
//Now PTRL AND PTRS WERE SYNCHRONIZED
//Now,Find the merge point
while(PTRL->next != PTRS->next){
PTRL = PTRL->next;
PTRS = PTRS->next;
}
return PTRL->data;
}
This code block at FindMergeNode is causing the problem
while(PTRL->next != PTRS->next) {
PTRL = PTRL->next;
PTRS = PTRS->next;
}
Let's say, we have the following entries for PTRL and PTRS
PTRL -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
PTRS -> 17 -> 6 -> 7 -> 8
Now, according to your implementation, PTRL will move ahead 4 times
(length of smaller linked list) and will point to 5. Then, your logic checks whether next of PTRL(which points to 6) is equal to next of PTRS(which points to 6). If they are equal (which they are, because both points to 6), the method returns data of PTRL, which is 5 at that point.
Change condition in while loop to PTRL != PTRS and I think this should solve your problem.
I am solving a coding challenge. In this challenge, we would be given two linked lists (2 -> 4 -> 3) and (5 -> 6 -> 4) and we have to return the result of their addition (7 -> 0 -> 8).
While I did solve it, I found a better version on Google:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode preHead(0), *p = &preHead;
int extra = 0;
while (l1 || l2 || extra) {
int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
extra = sum / 10;
p->next = new ListNode(sum % 10);
p = p->next;
l1 = l1 ? l1->next : l1;
l2 = l2 ? l2->next : l2;
}
return preHead.next;
}
However, I don't understand the step ListNode preHead(0), *p = &preHead;. The address of preHead is being stored in the pointer variable p. In other words, p points to preHead. Then, why is preHead.next being returned in the end? Note that this code does compile and return the expected output.
Appreciate your help!
I like to call it the Dummy Node Pattern. It's where the user will construct an unused node for the purpose of making things like insertion and lookup a lot easier to implement. As you can see in the function, p already points to a valid node to begin with, so there is no need to check if p is NULL and set it to a node of this is true, rather we just append a node using p->next. This is the alternative code where p's starting value is NULL:
ListNode* p = nullptr;
ListNode* tail;
while (l1 || l2 || extra) {
//int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
//extra = sum / 10;
if (p != nullptr) {
tail->next = new ListNode(sum % 10);
tail = tail->next;
} else {
tail = p = new ListNode(sum % 10);
}
//l1 = l1 ? l1->next : l1;
//l2 = l2 ? l2->next : l2;
}
return p;
We would have to keep an extra pointer to the end of the list so we know where to insert at each iteration. And we have to make sure p is not a null pointer in the case of inserting for the first time.
The reason preHead.next is returned is because preHead.next is where the insertion begins (it is the head of the actual linked list we want to return).
The following line:
p->next =new ListNode(sum % 10);
Allocates the new node that is returned.
In the first iteration of the loop, *p is the same as preHead. Later iterations move p, but do not invalidate preHead holding a pointer to the first new element added.
Then, why is preHead.next being returned in the end?
Because addTwoNumbers returns a pointer but preHead is a stack variable (i.e. a temporary); returning a temporary reference as a pointer to be de-referenced later is undefined behavior.
However, preHead.next is a heap allocated variable and can then be properly de-referenced when it needs to be.
When I see the implement of levelDB's cache, address. I can not understand why it use while loop in for loop(in function Resize), and I think it can replace by if statement. I hope someone can help me.
void Resize() {
uint32_t new_length = 4;
while (new_length < elems_) {
new_length *= 2;
}
LRUHandle** new_list = new LRUHandle*[new_length];
memset(new_list, 0, sizeof(new_list[0]) * new_length);
uint32_t count = 0;
for (uint32_t i = 0; i < length_; i++) {
LRUHandle* h = list_[i];
while (h != NULL) {
LRUHandle* next = h->next_hash;
uint32_t hash = h->hash;
LRUHandle** ptr = &new_list[hash & (new_length - 1)];
h->next_hash = *ptr;
*ptr = h;
h = next;
count++;
}
}
assert(elems_ == count);
delete[] list_;
list_ = new_list;
length_ = new_length;
}
};
list_ is apparently an array of linked lists. while (h != NULL), combined with h = next (where next is h->next_hash), means the while loop will operate on all the elements of every linked list, stopping only when the last element is reached (when h becomes NULL, either because the list was empty or because next_hash of an element was NULL).
If you replaced it with if (h != NULL), it would only work on the first element of the linked list.
It looks like list_ is a dynamic array of singly linked lists.
I assume the list_ looks something like the following
list_[0]-> node_1 -> node_2 -> null
list_[1]-> node_3 -> null
list_[2]-> null
....
list_[n]-> node_m-1 -> node_m -> null
To properly copy all of the elements into new_list you need to use the while loop. Otherwise any element that is not directly addressable from list_ will not be copied/hashed into the new_list. In the above diagram that would mean node_2 and node_m+1 would not be added to the new_list.
The new_list will keep the same shape but should have fewer collisions.
Using an if statement the new_list would look something like:
new_list[0]-> node_1 -> null
new_list[1]-> null
new_list[2]-> node_2 -> null
...
new_list[p-1]-> node_k -> null
new_list[p] -> null
That is each item in new_list would point to a list of 1 or zero elements.
Note node_1 in this diagram isn't necessarily the same as node 1 in the above diagram.
Using an If statement instead of a while loop will also lead to a memory leak since you can no longer access all of the elements.
Variable list_[i] has a sub list, while inside the for loop is looping over the sub list.
The if-statement doesn't work, if you have two elements list_[i] and list_[j] are both hashed to a same index new_list[m]. In such a case, you have to use while-statement to merge two buckets. Meanwhile, the length of every bucket in this implementation is less than 1 on average, so the while-statement here is actually as fast as the if-statement.
I have written a function to merge two singly linked lists. For example, if A = 1 2 3 and B = 3 4 5 and I merge them both, I get A = 1 2 3 3 4 5 and B = NULL. What I want to do now is to write a function which sorts a singly linked list using the mergesort algorithm (somehow using my merge function). For mergesort, if I'm not wrong, I would have to break the linked list in half in some way and then do the rest of the work. I have a small outline written down on how I want to do it. I'm not sure how I would go about doing the splitting at the moment. Any help is appreciated!
List mergeSort(List L) {
if(|L| > 1) {
split L into L1 and L2;
L1 = mergeSort(L1);
L2 = mergeSort(L1);
return(merge(L1,L2));
}
}
My merge function below:
void mylist::merge(mylist& b)
{
if (!this->isSorted() || !b.isSorted())
cout << "error" << endl;
Node* ptr1 = b.head;
Node* prev_a = NULL;
Node* curr_a = head;
Node* curr_b = ptr1;
while (curr_b) {
if (curr_a && head->key < ptr1->key) {
prev_a=curr_a;
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b; // curr_b is first element in 'a'
prev_a = curr_b;
curr_b = b_next;
}
return;
}
To divide the list into two halves, two pointers can be used.
Both pointers start at the head of the list. One pointer move every two steps, while the other
move one step each time.
When the fast pointer reach null, the slower pointer will points to the middle of the list.
ListNode *fast(head->next), *slow(head);
while(fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
I have the solution code here:
// Pre-condition: The fronts of two linked lists are provided.
// Post-condition: A linked list is returned that is the result of
// interleaving the elements from each provided list.
// (e.g. {1, 2, 3} & { 4, 5, 6} would return {1, 4, 2, 5, 3, 6}
Node* interleave( Node*& front1, Node*& front2 ) {
if( !front1 ) return front2;
if( !front2 ) return front1;
Node* third = front1->next; //this will become the third element
Node* fourth = front2->next; // this will be come the fourth element
front1->next = front2;
front2->next = third;
third = interleave(third, fourth);
return front1;
}
I kind of understand it but i would never be able to come up with something like this since i'm very bad at recursion. Is there another way to do this problem non-recursively? if so could you give me a hint? I tried this:
Node* interleave( Node*& front1, Node*& front2 ) {
Node* newNode = new Node;
while(front1!=NULL && front2!=NULL){
newNode = front1->next;
newNode = front2->next;
front1 = front1->next;
front2 = front2->next;
}
return newNode;
}
I'm sure it's wrong but that's the only thing i can come up with right now. Please help. Thank you
Try drawing two linked lists in parallel on a sheet of paper. Put some numbers in the nodes, just to tell them apart. Consider how you would reconnect them to form a single list, starting at the head (or "front") and working down. Note that you have to keep track of a few special nodes, like the first node of the resultant list and a couple of others. The pattern should become clear.
(Note that there's no need to construct a new node with new.)
There are a few mistakes in your code:
Node* interleave( Node*& front1, Node*& front2 )
I don't see the need for a reference to a pointer, since the first item in front1 will keep on being the first, and you don't need to mess with front2 at all.
Node* newNode = new Node;
while(front1!=NULL && front2!=NULL){
newNode = front1->next;
This is causing a memory leak - you're allocating at least sizeof(Node) bytes, but then you're losing the reference to the pointer, and you won't be able to delete it anymore.
Also, you're not doing anything with newNode, so you might throw it away as well.
front1 = front1->next;
front2 = front2->next;
Basically you're telling that front1 will rather point to the next element, and since you passed a reference to front1, you're altering the real pointer. Eventually, front1 or front2 will be NULL and the loop will terminate, so at least one of the two given parameters will become useless. You're never changing next, so the order will be left unchanged - you're just walking through the lists.
One approach could be to set front2's value to front1->next, then swap pointers and iterate again:
Node *a = front1, *b = front2;
while (a && b) {
Node* tmp = a->next;
a->next = b;
b = tmp;
a = a->next;
}
return front1;
I didn't test this, but it should be close to working. You can replace the verbose swap code with std::swap() if you're using stl.
The idea is simple: suppose you have two lists:
A -> B -> C -> NULL
D -> E -> F -> NULL
you say that A's next item is going to be the first element in the second list, so D:
A -> D -> E -> F -> NULL
and then the second lists becomes the ancient A's successor, so just B -> C -> NULL. You then advance a to point to its new next, or D, so you now have:
D -> E -> F -> NULL
B -> C -> NULL
and you repeat:
D -> B -> C -> NULL
E -> F -> NULL
B -> C -> NULL
F -> NULL
and so on until a NULL is met. Then front1, that still points to A, should have the right sequence (that is, unless I'm terribly wrong :p )