How to reverse a linked list - c++

I was working on Stack Overflow and came up across the #92.
Reverse a linked list 2 question. This is the question's description:
Given the head of a singly linked list and two integers left and right
where left <= right, reverse the nodes of the list from position left
to position right, and return the reversed list. For example, given
the linked list [1,2,3,4,5] 1, 4 the list should become [4,2,3,1,5]
It works for all runs but my code produces the wrong answer for one test case, which doesn't make sense. given. [1,2,3,4] 1,4 with 1 being left position an 4 being right position what makes sense for the list to become is [4,2,3,1] which is what my code produces. The correct answer they display is [4,3,2,1] which is screwing with my head and I can't understand why it's doing that. Any heads up are appreciated.
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right)
{
int x = 1;
ListNode * left_node = nullptr;
ListNode * right_node = nullptr;
ListNode * curr = head;
int temp = 0;
if (!head)
return nullptr;
while(curr)
{
if(x == left)
left_node = curr;
if(x == right)
right_node = curr;
curr = curr->next;
++x;
}
temp = left_node->val;
left_node->val = right_node->val;
right_node->val = temp;
return head;
}

Your solution implements swapping the values for the 2 indexes left and right, which matches the example given in the question.
But the question was to reverse the list between left and right, not just swap the two end points. So 1,2,3,4 becoming 4,3,2,1 is the correct solution and both the example and your solution are wrong, they only swap the entpoints.
PS: Most languages start counting at 0.

#Goswin Von Brederlow has already pointed out what is wrong, I will add a visual representation of what you are doing. Can you spot the problem?
EDIT: You can look in the comments for a better solution in terms of time and space (and also for a worse one).
After the while you should traverse the linked list. Since you don't have a "prev" (no double linked list) you need to traverse it multiple times to reverse it. I prepared a visualization of the algo, which uses a copy from left to right. And a support node for the prev node at each iteration. It uses idx and oidx to keep track of the position in the original and copied list.
And here are the steps of the iteration:

Related

Swapping linked list elements

I try to swap two nodes in a linked list as follows:
void swapTwo(course*& first, course*& second)
{
auto temp = first;
first = second;
second = temp;
second->next = first->next; // error right here due to self-referencing
first->next = second;
}
I got an error because second->next is already self-referencing. Is there an elegant solution to this? I can create 2 courses elements and re-construct first and second, but that seems so brute. Thanks!
You need to take multiple scenarios into account.
When the two aren't adjacent, nor is any of them the head or the tail
When they're adjacent
When either is the head or the tail
When one is the head while the other is the tail
When they're the only two in the linked list.

Sorting a singly Linked List

void NodeList::sortNodeAscending()
{
Node* swap = NULL;
Node* saveLink = NULL;
for(Node* firstPointer = head; firstPointer;firstPointer = firstPointer->next)
for(Node* secondPointer = firstPointer->next; secondPointer;secondPointer = secondPointer->next)
{
if((secondPointer->studentId)<(firstPointer->studentId))
{
swap =firstPointer;
saveLink = secondPointer->next;
firstPointer = secondPointer;
secondPointer = swap;
firstPointer->next = secondPointer;
secondPointer->next = saveLink;
}
}
}
This is my code for sorting but the problem that i have is after sorting, all the values are correct but the head is not changed or sorted.
Output:
{ 5, 0, 1, 2, 3, 4, 12, 15}
All the elements are sorted except the first node.
Note: I have already checked the question in the link below and it is different from my question. Sorting a Singly Linked List With Pointers
You are not updating head to point to the new start of the list.
At the end of the first iteration of the outer loop, firstPointer will point to the smallest element and can be updated to the new head.
Sorting of list is not as easy as it appears in your code:
[prev1] [first] [next1] ... [prev2] [second] [next2]
should look like this upon swapping first with second:
[prev1] [second] [next1] ... [prev2] [first] [next2]
How to do that:
Store next1 or next2, and keep track of prev1 and prev2 all the time as you can't look back in singly linked list.
first->next = next2 and second->next = next1
prev1->next = second and prev2->next = first
During all this, you need to take special care for list's head.
As pointed out by Kenny Ostrom, even if the head issues are fixed, if the initial sequence of student id's is 5,3,1,4,2, then the sort ends up with 5,1,3, not sorted and losing two values.
The code is swapping firstPointer and secondPointer, which are used as the inner and outer loop variables. This creates a problem.
When swapping nodes in a linked list, the nodes may be adjacent (three next pointers rotated) or they may be non-adjacent (two pairs of next pointers swapped). To handle both cases with the same code, first swap whatever points to the two nodes to be swapped first (like swap prev1->next with prev2->next), then swap the two node's next pointers (like swap curr1->next with curr2->next).
Trying to use bubble sort or any swapping sort to sort a linked list is complicated because you need to keep track of two previous pointers to nodes as well as two current pointers to nodes.
It would be simpler to start off with an empty "sorted" list, then remove one node at a time from the original list, and insert the node into it's proper location into the "sorted" list. For this method, start off with Node * sorted = NULL; Once all nodes have been removed from the original list and inserted in order into "sorted", then set head = sorted, so that head points to the sorted list.
A much faster method to sort a linked list uses a small (25 to 32) array of pointers to nodes combined with a bottom up merge sort, but that is more than what is needed in this case.

Compare all elements of a singly linked list to each other (C++)

I am trying to implement a function that compares all nodes of a singly linked list to each other.
For example, let's assume I have a linked list with eight nodes. (I don't have a count that tells me that however)
I need to compare 1 with 2,3,4,5,6,7 and 8. Then I need to compare 2 with 3,4,5,6,7, and 8. Obviously, I can't compare 1 with 1, 8 with 8, and 2 with 1 after 1 and 2 were already compared.
I know this is a double for-loop, but I am having a hard time structuring this.
Can anyone provide any insight or pseudocode?
I assume it's something like this:
//I know already that the list is NOT empty. But I don't know if it contains only one node.
Node * current = list;
Node * compWith;
if (current->next != NULL)
{
for (current = list; current->next != NULL; current = current->next)
for (compWith = current->next; compWith->next != NULL; compWith = compWith->next)
//Compare here
}
However I am not entirely sure my loops are stopping at the correct time, and I think I'm doing double comparisons somewhere. Any insight or pseudocode?

Binary tree interview: implement follow operation

I was asked to implement a binary search tree with follow operation for each node v - the complexity should be O(1). The follow operation should return a node w (w > v).
I proposed to do it in O(log(n)) but they wanted O(1)
Upd. It should be next greater node
just keep the maximum element for the tree and always return it for nodes v < maximum.
You can get O(1) if you store pointers to the "next node" (using your O(log(n) algorithm), given you are allowed to do that.
How about:
int tree[N];
size_t follow(size_t v) {
// First try the right child
size_t w = v * 2 + 1;
if(w >= N) {
// Otherwise right sibling
w = v + 1;
if(w >= N) {
// Finally right parent
w = (v - 1) / 2 + 1;
}
}
return w;
}
Where tree is a complete binary tree in array form and v/w are represented as zero-based indices.
One idea is to literally just have a next pointer on each node.
You can update these pointers in O(height) after an insert or remove (O(height) is O(log n) for a self-balancing BST), which is as long as an insert or remove takes, so it doesn't add to the time complexity.
Alternatively, you can also have a previous pointer in addition to the next pointer. If you do this, you can update these pointers in O(1).
Obviously, in either case, if you have a node, you also have its next pointer, and you can simply get this value in O(1).
Pseudo-code
For only a next pointer, after the insert, you'd do:
if inserted as a right child:
newNode.next = parent.next
parent.next = newNode
else // left child
predecessor(newNode)
For both next and previous pointers:
if inserted as a right child:
parent.next.previous = newNode
newNode.next = parent.next
parent.next = newNode
else // left child
parent.previous.next = newNode
newNode.previous = parent.previous
parent.previous = newNode
(some null checks are also required).

How to reverse every k element of a linked list? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reverse every k nodes of a linked list
Say the linked list is <1,3,6,4,8,9,0,2>. Calling reversek(3) would result in <6,3,1,9,8,4,2,0>. I have written the reverse function which may be used as a helper function in reversek. Here's my reverse function which reverses from a given starting point to a given ending point:
void List::reverse(Node * & start, Node * & end)
{
Node *pter = start;
while (pter != NULL)
{
Node *tmp = pter->next;
pter->next = pter->prev;
pter->prev = tmp;
if (tmp == NULL)
{
endPoint = startPoint;
startPoint = pter;
}
pter = tmp;
}
I'm confused about how to implement reversek, any help is appreciated.
Try something like -
Have 2 pointers (P1, P2) to linked list head element.
One is used for traversing the list(P1). While the other(P2) is used for swapping the elements once the traversing point is reached 3rd node in the list.
Now move both the pointers to 4th node. And again continue P1 traversing rest of the list.
Here you have to keep track of when every 3rd node is reached by P1. Here it is 3 for example, but it depends on function argument.