Odd Even Linked List Run Time Error for one particular input. Runs fine for everything else - algorithm

I am trying to solve a problem from LeetCode.
Problem
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.
You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.
My Solution:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
ListNode *even, *firsteven, *odd, *curr;
if(head == NULL)
return NULL;
odd = head;
even = head;
curr = head;
if(head->next) {
even = even->next;
firsteven = head->next;
}
else return head;
if(head->next->next)
curr = head->next->next;
else return head;
while(curr) {
even->next = curr->next;
curr->next = NULL;
odd->next = curr;
curr->next = firsteven;
odd = odd->next;
even = even->next;
even->next ? curr = even->next : curr = NULL;
}
return head;
}
};
My solution works perfectly well for all inputs except for inputs of size 3.
For an input 1->2->3 I am getting a run time error. I have done a dry run several times. I am not sure why I am getting a run time error.
Can you please tell me what am I doing wrong?

The problem is with this line:
even->next = curr->next;
When current is set to the last element (3), you're trying curr->next, which will result in an error.

Related

TLE when solving "Removing duplicates from unsorted linked list" using maps in c++

I am trying to solve the removing duplicates from unsorted linked list problem on GFG using maps. I have figured out the accepted solution using insert and find commands:
Node * removeDuplicates( Node *head)
{
// your code goes here
map <int, int> duplicates;
Node* curr=head;
Node* prev=NULL;
while(curr){
if(duplicates.find(curr->data)==duplicates.end()){
duplicates.insert({curr->data,1});
prev=curr;
}
else{
prev->next=curr->next;
delete(curr);
}
curr=prev->next;
}
return head;
}
But another approach I tried earlier is giving TLE for submission, even though it works fine for example test case. I have tried to implement the same idea as above but in a slightly different way. Can anyone help me out with this?
Node * removeDuplicates( Node *head)
{
map <int, int> duplicates;
Node* temp=head;
while(temp){
duplicates[temp->data]=1;
temp=temp->next;
}
Node* curr=head;
Node* prev=NULL;
while(curr){
if(duplicates[curr->data]==1){
duplicates[curr->data]=0;
prev=curr;
}
else{
prev->next=curr->next;
delete(curr);
}
curr=prev->next;
}
return head;
}
There are multiple problems with the 2nd solution.
your running through a linked list twice, don't do this if possible.
unordered_map might be much faster as already mentioned in the commented
your looking more in the duplicates in the 2nd solution, 3 vs. 2.
Either of the above could further cause cache congestion slowing things down further.
Take the bool data type far value instead of int so you don't have to initialize the value of a map.
Instead of taking an ordered map use the unordered map which is relatively faster.
Here is the optimized code.
Node *removeDuplicates(Node *head)
{
Node *curr = head;
Node *prev = NULL;
if (curr == NULL)
return NULL;
unordered_map visited;
while (curr != NULL)
{
if (visited[curr->data])
{
Node *temp = curr;
curr = curr->next;
delete (temp);
prev->next = curr;
}
else
{
visited[curr->data] = true;
prev = curr;
curr = curr->next;
}
}
return head;
}

Reverse alternate elements and append to end of the list

Given a linked list as a->x->b->y->c->z , we need to reverse alternate element and append to end of list. That is , output it as a->b->c->z->y->x.
I have an O(n) solution but it takes extra memory , we take 2 lists and fill it with alternate elements respectively , so the two lists are a b c and x y z and then we will reverse the second list and append it to the tail of first so that it becomes a b c z y x .
My question is can we do it in place ? Or is there any other algorithm for the same ?
The basic idea:
Store x.
Make a point to b.
Make y point to the stored element (x).
Make b point to c.
etc.
At the end, make the last element at an odd position point to the stored element.
Pseudo-code: (simplified end-of-list check for readability)
current = startOfList
stored = NULL
while !endOfList
temp = current.next
current.next = current.next.next
temp.next = stored
stored = temp
current = current.next
current.next = stored
Complexity:
O(n) time, O(1) space.
Here is logic in recursion mode
public static Node alRev(Node head)
{
if (head == null) return head;
if (head.next != null)
{
if (head.next.next != null)
{
Node n = head.next;
head.next = head.next.next;
n.next = null;
Node temp = alRev(head.next);
if (temp != null){
temp.next = n;
return n;
}
}
else
return head.next;
}
else
return head;
return null;
}
This is a recent question from amazon interview, the Idea looks good and there seems to be no trick in it.
Java code with comments:
static void change(Node n)
{
if(n == null)
return;
Node current = n;
Node next = null, prev = null;
while(current != null && current.next != null)
{
// One of the alternate node which is to be reversed.
Node temp = current.next;
current.next = temp.next;
// Reverse the alternate node by changing its next pointer.
temp.next = next;
next = temp;
// This node will be used in the final step
// outside the loop to attach reversed nodes.
prev = current;
current = current.next;
}
// If there are odd number of nodes in the linked list.
if(current != null)
prev = current;
// Attach the reversed list to the unreversed list.
prev.next = next;
}
here the c code which don't uses any extra space for doing this..enjoy and have fun
in case of any doubt feel free to ask
#include<stdio.h>
#include<stdlib.h>
int n;
struct link
{
int val;
struct link *next;
};
void show(struct link *);
void addatbeg(struct link **p,int num)
{
struct link *temp,*help;
help=*p;
temp=(struct link *)malloc(sizeof(struct link));
temp->val=num;
temp->next=NULL;
if(help==NULL)
{
*p=temp;
}
else
{
temp->next=help;
*p=temp;
}
n++;
show(*p);
}
void revapp(struct link **p)
{
struct link *temp,*help,*q,*r;
r=NULL;
temp=*p;
help=*p;
while(temp->next!=NULL)
{
temp=temp->next;
q=r; //this portion will revrse the even position numbers
r=temp;
temp=temp->next;
//for making a connection between odd place numbers
if(help->next->next!=NULL)
{
help->next=temp;
help=help->next;
r->next=q;
}
else
{
r->next=q;
help->next=r;
show(*p);
return;
}
}
}
void show(struct link *q)
{
struct link *temp=q;
printf("\t");
while(q!=NULL )
{
printf("%d ->",q->val);
q=q->next;
if(q==temp)
{
printf("NULL\n");
return;
}
}
printf("NULL\n");
}
int main()
{
n=0;
struct link *p;
p=NULL;
// you can take user defined input but here i am solving it on predefined list
addatbeg(&p,8);
addatbeg(&p,7);
addatbeg(&p,6);
addatbeg(&p,5);
addatbeg(&p,4);
addatbeg(&p,3);
addatbeg(&p,2);
addatbeg(&p,1);
revapp(&p);
return 0;
}`

Implementing the Dutch National Flag Program with Linked Lists

I wanted to sort a linked list containing 0s, 1s or 2s. Now, this is clearly a variant of the Dutch National Flag Problem.
http://en.wikipedia.org/wiki/Dutch_national_flag_problem
The algorithm for the same as given in the link is:
"Have the top group grow down from the top of the array, the bottom group grow up from the bottom, and keep the middle group just above the bottom. The algorithm stores the locations just below the top group, just above the bottom, and just above the middle in three indexes. At each step, examine the element just above the middle. If it belongs to the top group, swap it with the element just below the top. If it belongs in the bottom, swap it with the element just above the bottom. If it is in the middle, leave it. Update the appropriate index. Complexity is Θ(n) moves and examinations."
And a C++ implementation given for the same is:
void threeWayPartition(int data[], int size, int low, int high) {
int p = -1;
int q = size;
for (int i = 0; i < q;) {
if (data[i] == low) {
swap(data[i], data[++p]);
++i;
} else if (data[i] >= high) {
swap(data[i], data[--q]);
} else {
++i;
}
}
}
My only question is how do we traverse back in a linked list like we are doing here in an array?
A standard singly-linked list doesn't allow you to move backwards given a linked list cell. However, you could use a doubly-linked list, where each cell stores a next and a previous pointer. That would let you navigate the list forwards and backwards.
However, for the particular problem you're trying to solve, I don't think this is necessary. One major difference between algorithms on arrays and on linked lists is that when working with linked lists, you can rearrange the cells in the list to reorder the elements in the list. Consequently, the algorithm you've detailed above - which works by changing the contents of the array - might not actually be the most elegant algorithm on linked lists.
If you are indeed working with linked lists, one possible way to solve this problem would be the following:
Create lists holding all values that are 0, 1, or 2.
Remove all cells from the linked list and distribute them into the list of elements that are equal to 0, 1, or 2.
Concatenate these three lists together.
This does no memory allocation and purely works by rearranging the linked list cells. It still runs in time Θ(n), which is another plus. Additionally, you can do this without ever having to walk backwards (i.e. this works on a singly-linked list).
I'll leave the complete implementation to you, but as an example, here's simple C++ code to distribute the linked list cells into the zero, one, and two lists:
struct Cell {
int value;
Cell* next;
}
/* Pointers to the heads of the three lists. */
Cell* lists[3] = { NULL, NULL, NULL };
/* Distribute the cells across the lists. */
while (list != NULL) {
/* Cache a pointer to the next cell in the list, since we will be
* rewiring this linked list.
*/
Cell* next = list->next;
/* Prepend this cell to the list it belongs to. */
list->next = lists[list->value];
lists[list->value] = list;
/* Advance to the next cell in the list. */
list = next;
}
Hope this helps!
As others have said, there is no way to "back up" in a linked list without reverse links. Though it's not exactly an answer to your question, the sort can be easily accomplished with three queues implementing a bucket sort with three buckets.
The advantage of queues (vice pushing on stacks) is that the sort is stable. That is, if there are data in the list nodes (other than the 0,1,2-valued keys), these will remain in the same order for each key.
This is only one of many cases where the canonical algorithm for arrays is not the best for lists.
There is a very slick, simple way to implement the queues: circularly linked lists where the first node, say p, is the tail of the queue and consequently p->next is is the head. With this, the code is concise.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_s {
struct node_s *next;
int val;
int data;
} NODE;
// Add node to tail of queue q and return the new queue.
NODE *enqueue(NODE *q, NODE *node)
{
if (q) {
node->next = q->next;
q->next = node;
}
else node->next = node;
return node;
}
// Concatenate qa and qb and return the result.
NODE *cat(NODE *qa, NODE *qb)
{
NODE *head = qa->next;
qa->next = qb->next;
qb->next = head;
return qb;
}
// Sort a list where all values are 0, 1, or 2.
NODE *sort012(NODE *list)
{
NODE *next = NULL, *q[3] = { NULL, NULL, NULL};
for (NODE *p = list; p; p = next) {
next = p->next;
q[p->val] = enqueue(q[p->val], p);
}
NODE *result = cat(q[0], cat(q[1], q[2]));
// Now transform the circular queue to a simple linked list.
NODE *head = result->next;
result->next = NULL;
return head;
}
int main(void)
{
NODE *list = NULL;
int N = 100;
// Build a list of nodes for testing
for (int i = 0; i < N; ++i) {
NODE *p = malloc(sizeof(NODE));
p->val = rand() % 3;
p->data = N - i; // List ends up with data 1,2,3,..,N
p->next = list;
list = p;
}
list = sort012(list);
for (NODE *p = list; p; p = p->next)
printf("key val=%d, data=%d\n", p->val, p->data);
return 0;
}
This is now a complete simple test and it runs just fine.
This is untested. (I will try to test it if I get time.) But it ought to be at least very close to a solution.
Using a doubly linked list. If you have already implemented a linked list object and the related link list node object, and are able to traverse it in the forward direction it isn't a whole bunch more work to traverse in the reverse direction.
Assuming you have a Node object somewhat like:
public class Node
{
public Node Next;
public Object Value;
}
Then all you really need to do is change you Node class and you Insert method(s) up a little bit to keep track of of the Node that came previously:
public class Node
{
public Node Next;
public Node Previous;
public Object Value;
}
public void Insert(Node currentNode, Node insertedNode)
{
Node siblingNode = currentNode.Next;
insertedNode.Previous = currentNode;
insertedNode.Next = siblingNode;
if(siblingNode!= null)
siblingNode.previous = insertedNode;
currentNode.next = insertedNode;
}
PS Sorry, I didn't notice the edit that included the C++ stuff so it's more C#
Works for all cases by CHANGING NODES rather than NODE DATA.. Hoping its never too late!
METHOD(To throw some light on handling corner cases):
1. Keep three dummy nodes each for 0,1,2;
2. Iterate throught the list and add nodes to respective list.
3. Make the next of zero,one,two pointers as NULL.
4. Backup this last nodes of each list.
5. Now handle 8 different possible cases to join these list and Determine the HEAD.
zero one two
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
An implementation of this in C++.
Node* sortList(Node *head)
{
struct Node dummyzero,dummyone,dummytwo;
dummyzero.next = dummyone.next = dummytwo.next = NULL;
struct Node *zero =&dummyzero,*one = &dummyone,*two=&dummytwo;
Node *curr = head,*next=NULL;
while(curr)
{
next = curr->next;
if(curr->data==0)
{
zero->next = curr;
zero = zero->next;
}
else if(curr->data==1)
{
one->next = curr;
one = one->next;
}
else
{
two->next = curr;
two = two->next;
}
curr = next;
}
zero->next = one->next = two->next =NULL; //Since this dummynode, No segmentation fault here.
Node *zerolast = zero,*onelast = one,*twolast = two;
zero = dummyzero.next;
one = dummyone.next;
two = dummytwo.next;
if(zero==NULL)
{
if(one==NULL)
head = two;
else
{
head = one;
onelast->next = two;
}
}
else
{
head = zero;
if(one==NULL)
zerolast->next = two;
else
{
zerolast->next = one;
onelast->next = two;
}
}
return head;
}
The idea is to use dutch flag sorting algorithm, with a slight modification:
sort 0's and 1's as per dutch flag method,
But for 2's instead of adding them at the end of list, keep them in a separate linked list.
And finally append the 2's list to the sorted list of 0's and 1's.
Node * sort012_linked_list(Node * head) {
if (!head || !head->next)
return head;
Node * head_of_2s = NULL;
Node * prev = NULL;
Node * curr = head;
while (curr) {
if (curr->data == 0) {
if (prev == NULL || prev->data == 0) {
prev = curr;
curr = curr->next;
}
else {
prev->next = curr->next;
curr->next = head;
head = curr;
curr = prev->next;
}
}
else if (curr->data == 1) {
prev = curr;
curr = curr->next;
}
else { // curr->data == 2
if (prev == NULL) {
head = curr->next;
curr->next = head_of_2s;
head_of_2s = curr;
curr = head;
}
else {
prev->next = curr->next;
curr->next = head_of_2s;
head_of_2s = curr;
curr = prev->next;
}
}
}
if (prev)
prev->next = head_of_2s;
return head;
}

swapping adjacent nodes of a LinkedList

I have to swap two adjacent node(not their data) in a linked list.
e.g.
1) Input a->b->c->d->e->f, Output : b->a->d->c->f->e
2) Input a->b->c->d->e, Output : b->a->d->c->e
I have writen the following code is there any more efficient way (maybe with two temporary pointers) or simple logic?
node* swap(node* head) {
node *first = head;
node *second,*third,*result;
if(head == NULL || head->next == NULL) {
return head;
}
result = second = first->next;
third = second->next;
while(second != NULL) {
second->next=first;
first->next=(third->next==NULL ? third : third->next);
first=third;
second=(third->next==NULL ? third : third->next);
third=(second==NULL ? second : second->next);
}
return result;
}
Looks good. I added one correctness check (third==NULL) and removed one redundant expression. You are going through the whole list only once, which you have to do. So I think we can be pretty certain that this is the fastest way to do it.
node* swap(node* head) {
node *first = head;
node *second,*third,*result;
if(head == NULL || head->next == NULL) {
return head;
}
result = second = first->next;
third = second->next;
while(second != NULL) {
second->next=first;
second = first->next=((third==NULL || third->next==NULL) ? third : third->next);
first=third;
third=(second==NULL ? second : second->next);
}
return result;
}
You can do this fairly simply with a recursion:
// Swaps node b and c.
void swapTwo(node* a, node* b, node* c) {
if (a != NULL)
a->next = c;
b->next = c->next;
c->next = b;
}
void swapEveryTwo(node* prev, node* node) {
if (node != null && node->next != null) {
swapTwo(prev, node, node->next);
swapEveryTwo(node->next, node->next->next);
}
}
Every call of swapEveryTwo swaps pairs of nodes, and then sets up the recursion for the next pair. Also, because this function is tail recursive, the compiler will undoubtedly optimize it to a while loop, ensuring no extra stack frames are allocated, and thus will be optimal. If you need further explanation, feel free to ask.
Edited to add swap function as in original post:
node* swap(node *head) {
if (head != NULL && head->next != NULL) {
node *newHead = head->next;
swapEveryTwo(NULL, head);
return newHead;
} else {
return head;
}
}
Your algorithm is about the best possible. Often we can get a bit of speed through simplicity. Instead of drawing pictures and reasoning about pointers, think of popping elements off the head of the input list and using a queue add-to-tail operation to build up the result. In pseudocode, we have
set_empty(rtn);
while (head) {
fst = pop(head);
if (head) {
snd = pop(head);
add_at_tail(rtn, snd);
}
add_at_tail(rtn, fst);
}
The if is needed only to protect against the case where the input list has odd length. If we're sure the list is even in length, we can skip it.
Now pop is very easy to implement. The add-to-tail operation is easiest if we use a dummy head node. So in C, we have:
node *swap(node *head)
{
node dummy[1]; // set_empty(rtn);
node *rtn = dummy;
while (head) {
node *fst = head; // fst = pop(head);
head = head->next;
if (head) {
node *snd = head; // snd = pop(head);
head = head->next;
rtn->next = snd; // add_to_tail(rtn, snd);
rtn = rtn->next;
}
rtn->next = fst; // add_to_tail(rtn, fst);
rtn = rtn->next;
}
rtn->next = NULL; // terminate tail
return dummy->next;
}
Now I have not tested this code, but I'm pretty sure it will run fine modulo maybe a typo or two. There are fewer tests than yours (just one per element). Tests are comparatively expensive because they can interfere with pipelining, so mine ought to run just a tad faster. Almost certainly this difference is irrelevant.
However, I think my code rather simpler to understand. Of course that's just one biased opinion, but readability does count during maintenance.
NB Now I have done a quick test and it worked on the first try! On the other hand when I tried your code I got a segv at
first->next=(third->next==NULL ? third : third->next);
Below is the test frame. Do you see anything wrong?
typedef struct node_s {
struct node_s *next;
int val;
} node;
// swap goes here
int main(void)
{
node dummy[1];
node *p = dummy;
for (int i = 0; i < 16; i++) {
p->next = malloc(sizeof(node));
p = p->next;
p->next = NULL;
p->val = 'a' + i;
}
p = swap(dummy->next);
while (p) {
printf("%c ", p->val);
p = p->next;
}
printf("\n");
return 0;
}
In JavaScript
LinkedList.prototype.swapPairs = function() {
var recurse = function(current) {
if (!current) return this;
if (current.next) {
var save = current.next.value;
current.next.value = current.value;
current.value = save;
current = current.next;
}
return recurse(current.next);
}.bind(this);
return recurse(this.head);
}
Alex DiCarlo's recursion method is simpler but needs to be corrected slightly.
void swapEveryTwo(node* prev, node* node) {
if (node != null && node->next != null) {
swapTwo(prev, node, node->next);
swapEveryTwo(node, node->next);
}
}
Please correct me if I am wrong.
Thanks!

Reversing a singly linked list when a block size is given

There is a singly connected linked list and a block size is given.For eg if my linked list is 1->2->3->4->5->6->7->8-NULL and my block size is 4 then reverse the first 4 elements and then the second 4 elements.The output of the problem should be 4->3->2->1->8->7->6->5-NULL
I was thinking of dividing the linked list into segments of size 4 and then reversing it.
But that way I am forced to use a lot of extra nodes which is not desired at all.
The space complexity should be kept to a minimum.
It will be highly appreciable if someone can come with a better solution where the usage of extra nodes would be kept to a minimum.
I tried this...seems to work fine...
node* reverse(node* head) // function to reverse a list
{
node* new_head = NULL;
while(head != NULL)
{
node* next = head->next;
head->next = new_head;
new_head = head;
head = next;
}
return new_head;
}
node* reverse_by_block(node* head, int block)
{
if(head == NULL)
return head;
node* tmp = head;
node* new_head = head;
node* new_tail = NULL;
int count = block;
while(tmp != NULL && count--)
{
new_tail = tmp;
tmp = tmp->next;
}
new_tail->next = NULL;
new_tail = new_head;
new_head = reverse(new_head);
new_tail->next = reverse_by_block(tmp,block);
return new_head;
}
You can advance swapping the current element with the next 3 times: 1234, 2134, 2314, 2341. Then do it twice to get 3421. Then once to get 4321. Then advance 4 steps and repeat the process with the next block.
This can be done in linear-time, with constant space.
Here is a brief description:
Split the linked list into two parts by block-size
int split(node* head, node** listA, node** listB size_t block_size)
{
node* cur = head;
while(block_size && cur)
{
cur = cur->next;
--block_size;
}
if(!cur) { /* error : invalid block size */ return -1; }
*listA = head;
*listB = cur->next;
cur->next = NULL; /* terminate list A */
return 0;
}
Reverse the two sub-parts, (use a non-recursive linear time, constant space function)
reverse(listA);
reverse(listB);
Link them to get the desired linked list.
cur = *listA;
/* goto last but one element of listA */
while(cur->next) cur = cur->next;
cur->next = *listB;

Resources