Swap two ListNode* in C++ - c++

Please help, I am totally lost here. This is leetcode problem no. 24, swap nodes in pairs.
I am getting this error in screeshot.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
void recurse(ListNode* head){
if(head!=nullptr and head->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next;
current->next = previous->next->next;
previous->next->next = current;
recurse(current);
}
}
public:
ListNode* swapPairs(ListNode* head) {
auto front = new ListNode(0, head);
recurse(front);
return front->next;
}
};

UPD: I add some comments to illustrate the OP's correct solution:
if(head!=nullptr and head->next!=nullptr
and head->next->next!=nullptr){
// p->[c]->[x]->y; swap(c, x); y can be null
auto previous = head, current = head->next;
// p->c->x->y
previous->next = current->next;
// p->x->y; c->x->y
current->next = previous->next->next;
// c->y; p->x->y
previous->next->next = current;
// p->x->c->y
recurse(current);
}
original answer 👇
if(head!=nullptr and head->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next; // previous->next = head->next->next
current->next = previous->next->next; // current->next = head->next->next->next
previous->next->next = current;
recurse(current);
}
In this if branch you only checked the head and head->next valid.
However you are attempt to invoke head->next->next->next later. Since head->next->next can be nullptr, your program will stop here.
You can find the right solution in the leetcode platform, and here I only reply on why this code doesn't work.

Thank you tieway59, you were right I just figured it out by myself. I was missing one more validation of head->next->next in if block of recurse function.
Here's my working code :
class Solution {
void recurse(ListNode* head){
if(head!=nullptr and head->next!=nullptr
and head->next->next!=nullptr){
auto previous = head, current = head->next;
previous->next = current->next;
current->next = previous->next->next;
previous->next->next = current;
recurse(current);
}
}
public:
ListNode* swapPairs(ListNode* head){
auto front = new ListNode(0, head);
recurse(front);
return front->next;
}
};

To swap two existent adjacent nodes of a list there is no need to create a new node as you are doing
auto front = new ListNode(0, head);
Otherwise there will be a memory leak.
Instead what you need is to pass a pointer to a node by reference.
There is already standard function std::swap in the C++ library that can be used in your recursion function.
Here is a demonstration program.
#include <iostream>
#include <utility>
#include <functional>
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
void clear( ListNode * &head )
{
while ( head )
{
delete std::exchange( head, head->next );
}
}
void create( ListNode * &head, const int a[], size_t n )
{
clear( head );
for ( ListNode **current = &head; n--; current = &( *current )->next )
{
*current = new ListNode( *a++ );
}
}
std::ostream & display( const ListNode * head, std::ostream &os = std::cout )
{
for ( const ListNode *current = head; current != nullptr; current = current->next )
{
os << current->val << " -> ";
}
return os << "null";
}
void swap( ListNode * &current )
{
if ( current && current->next )
{
ListNode * &next = current->next;
std::swap( current, next );
std::swap( current->next, next->next );
swap( next );
}
}
int main()
{
ListNode *head= nullptr;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( head, a, sizeof( a ) / sizeof( *a ) );
display( head ) << '\n';
swap( head );
display( head ) << '\n';
clear( head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 0 -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> null

Related

C++ reordering Singly Linked List

Hi I'm trying to write a code for singly linked list that reorders the nodes so that:
L1->L2->L3->...->Ln to L1->Ln->L2->Ln-1->L3->Ln-2...
So I tried to do this by finding the node at the end of the list and setting that node as the next of current node and then finishing the loop by setting the current node as the next next of current node.
#include <cstdlib>
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* newNode(int x){
ListNode* temp = new ListNode;
temp->val = x;
temp->next = NULL;
return temp;
}
void printlist(ListNode* head)
{
while (head != NULL) {
cout << head->val << " ";
if (head->next)
cout << "-> ";
head = head->next;
}
cout << endl;
}
void reorderList(ListNode* head){
ListNode *curr = head;
ListNode *temp=head;
ListNode *last=NULL;
while(curr->next != NULL){
while(temp->next != NULL){
temp=temp->next;
last=temp;
}
curr->next=last;
last->next=curr->next->next;
curr=curr->next->next;
temp=curr->next;
}
}
int main(int argc, char** argv) {
ListNode* head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
printlist(head); // Print original list
reorderList(head); // Modify the list
printlist(head); // Print modified list
return 0;
}
So far, after displaying the original list, the program stops by saying that the run failed. I'm having some problem understanding the singly linked list and I don't know what I'm doing wrong.
I have modified your code to show a correct answer:
#include <iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode(): val( 0 ), next( nullptr ) {}
ListNode( int x ): val( x ), next( nullptr ) {}
ListNode( int x, ListNode* next ): val( x ), next( next ) {}
};
void printlist( ListNode* head )
{
while( head != nullptr ) {
std::cout << head->val << " ";
if( head->next )
std::cout << "-> ";
head = head->next;
}
std::cout << std::endl;
}
void reorderList( ListNode* head ) {
ListNode* pf = head;
ListNode* pt = nullptr;
ListNode* tmp = nullptr;
while( true )
{
// find n-1 node
tmp = pf;
while( tmp && tmp->next && tmp->next->next )
tmp = tmp->next;
// check to see n-1 node is not equal to the first node
if( tmp == pf )
break;
// reorder
pt = tmp;
tmp = pf->next;
pf->next = pt->next;
pt->next->next = tmp;
pf = tmp;
pt->next = nullptr;
}
}
int main( int argc, char** argv ) {
ListNode* head = new ListNode( 1 );
head->next = new ListNode( 2 );
head->next->next = new ListNode( 3 );
head->next->next->next = new ListNode( 4 );
head->next->next->next->next = new ListNode( 5 );
head->next->next->next->next->next = new ListNode( 6 );
printlist( head ); // Print original list
reorderList( head ); // Modify the list
printlist( head ); // Print modified list
return 0;
}
and the result is like below:
1 -> 2 -> 3 -> 4 -> 5 -> 6
1 -> 6 -> 2 -> 5 -> 3 -> 4
There could be many solutions to your problem. I just modified your logic and added comments which could help you to understand. Happy link list coding.
#include <cstdlib>
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* newNode(int x){
ListNode* temp = new ListNode;
temp->val = x;
temp->next = NULL;
return temp;
}
void printlist(ListNode* head)
{
while (head != NULL) {
cout << head->val << " ";
if (head->next)
cout << "-> ";
head = head->next;
}
cout << endl;
}
void reorderList(ListNode* head){
ListNode *curr = head;
ListNode *temp=head;
ListNode *last=NULL,*prev;
while(curr->next != NULL){
while(temp->next != NULL){
//Prev variable is being used for remove last node connection from it previous node
// For example 1->2->3
// We need to remove 2->3 connection before adding 1->3
// Otherwise it will create cycle i.e 1->3->2->3->2....
prev = temp;
temp=temp->next;
last=temp;
}
// If node number is even this condition will check adding mid+1 node twice
if(last==NULL) {
break;
}
temp = curr->next;
curr->next=last;
last->next=temp;
curr=curr->next->next;
temp=curr->next;
// Removing last node connection from it previous node
prev->next = NULL;
last = NULL;
}
}
int main(int argc, char** argv) {
ListNode* head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
//head->next->next->next->next->next = newNode(8);
printlist(head); // Print original list
reorderList(head); // Modify the list
printlist(head); // Print modified list
return 0;
}

SUMMARY: UndefinedBehaviorSanitizer

Trying to solve Odd Even Linked List question.
Given the head of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.
My try:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
int n = 1;
ListNode* l = nullptr;
ListNode *u = l;
ListNode* r = r;
ListNode* ru = nullptr;
while(head){
ListNode* c = new ListNode(head->val);
if(n%2){
if(r == nullptr){
r = c;
}
else{
r->next = c;
r = r->next;
}
}
else{
if(l == nullptr){
l = c;
}
else{
l->next = c;
l = l->next;
}
}
n++;
head=head->next;
}
l->next = ru;
return u;
}
};
But getting the below error:
Line 27: Char 24: runtime error: member access within misaligned address 0x9ddfea08eb382d69 for type 'ListNode', which requires 8 byte alignment (solution.cpp)
0x9ddfea08eb382d69: note: pointer points here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:36:24
What does the error mean and to solve it.
Link: https://leetcode.com/problems/odd-even-linked-list/
The problem is (once we fix the typo):
ListNode *l = nullptr;
ListNode *u = l;
...
return u;
u is always nullptr. One quick hack would be:
ListNode *l = nullptr;
ListNode **u = &l;
ListNode *r = nullptr;
ListNode **ru = &r;
...
l->next = *ru;
return *u;
Or you could try:
if(r == nullptr){
r = c;
ru = r; // Add this
}
...
if(l == nullptr){
l = c;
u = l; // Add this
}
Please check the code with comments marked as // CHANGE HERE
Tested here: https://godbolt.org/z/c3e5M739d
#include <iostream>
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution
{
public:
ListNode* oddEvenList(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
int n = 1;
// CHANGE HERE: set all to nullptr
ListNode* l = nullptr;
ListNode* u = nullptr;
ListNode* r = nullptr;
ListNode* ru = nullptr;
while(head){
// std::cout << head->val << " ";
ListNode* c = new ListNode(head->val);
if(n%2){
// CHANGE HERE: replace r with ru
if(ru == nullptr){
r = c;
// CHANGE HERE: set ru
ru = r;
}
else{
r->next = c;
r = r->next;
}
}
else{
// CHANGE HERE: replace l with u
if(u == nullptr){
l = c;
// CHANGE HERE: set u
u = l;
}
else{
l->next = c;
l = l->next;
}
}
n++;
head=head->next;
}
l->next = ru;
return u;
}
};
int main()
{
ListNode* node = new ListNode(1);
node->next = new ListNode(2);
node->next->next = new ListNode(3);
node->next->next->next = new ListNode(4);
node->next->next->next->next = new ListNode(5);
node->next->next->next->next->next = new ListNode(6);
Solution s;
ListNode* l = s.oddEvenList(node);
ListNode* q = l;
while (q)
{
std::cout << q->val << " ";
q = q->next;
}
}

c++ why returning pointer works, but returning address not?

I have the following code where I first define struct ListNode to represent an integer, then a function receiving two integers as ListNodes and returning their sum:
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* addTwoNumbers( ListNode* l1, ListNode* l2 ) {
ListNode head;
ListNode* dummy = &head;
ListNode* pNode1 = l1;
ListNode* pNode2 = l2;
int i1, i2, value;
int takeover = 0;
while( pNode1 != nullptr || pNode2 != nullptr )
{
i1 = ( pNode1 != nullptr )? pNode1 -> val : 0;
i2 = ( pNode2 != nullptr )? pNode2 -> val : 0;
value = i1 + i2 + takeover;
takeover = value / 10;
(dummy -> val) = value % 10;
dummy -> next = new ListNode();
dummy = dummy -> next;
if ( pNode1 != nullptr)
pNode1 = pNode1 -> next;
if ( pNode2 != nullptr )
pNode2 = pNode2 -> next;
}
if ( takeover > 0 )
dummy -> val = takeover;
return &head;
}
....
ListNode* l1=..., l2 = ...;
ListNode* pN = new ListNode;
pN = addTowNumbers(l1, l2);
but now pN is equal nullptr;
but if in the function definition of addTwoNumbers, we use
ListNode* head;
ListNode* head;
ListNode* dummy = head;
....
return head;
it would work; why?
The mistake is here.
ListNode head;
ListNode* dummy = &head;
head is initialized locally, that means after function call, it is expired. Create dummy node like below.
ListNode *dummy = new ListNode(0);
Another mistake. You don't need to initialize pN variable. You can directly assign the result of the function.
ListNode* pN = addTowNumbers(l1, l2);

Move and copy constructors in a linked list

I am still trying to learn more about copy and move constructors. I have a linked list class that I want to deep copy using copy and move constructors but I'm having issues. First, to deep copy List class, do I only copy head_ and tail_ in the constructors. I know the code is horrendous, maybe I shouldn't jump into high-level stuff right away.
Any help is appreciated!
template<typename T>
class List
{
public:
class Node {
public:
Node(T value) : value_(value) {}
T value_;
Node* next_;
Node* prev_;
};
Node* head_;
Node* tail_;
//! Default constructor
List() :tail_(nullptr) {}
//! Copy constructor
List(const List& lst) : head_(nullptr) {
//not sure what goes in here
}
}
//! Move constructor
List(List&& move) {
head_ = move.head_;
move.head_ = nullptr;
tail_ = move.tail_;
move.tail_ = nullptr;
}
//! Copy assignment operator
List& operator= (const List& list) {
tail_ = nullptr;
head_ = tail_;
Node* current = list.head_;
Node* next = list.head_->next_;
Node* replace = head_;
while (next != list.tail_) {
current = current->next_;
next = next->next_;
replace->next_ = tail_;
replace->next_->value_;
replace = replace->next_;
}
return *this;
}
//! Move assignment operator
List& operator= (List&& other) {
tail_ = nullptr;
head_ = tail_;
head_->next_ = other.head_->next_;
Node* current = other.head_;
Node* next = other.head_->next_;
while (next != other.tail_) {
current = current->next_;
next = next->next_;
}
current->next_ = tail_;
other.head_->next_ = other.tail_;
return *this;
}
Here is my five cents.:)
The demonstrative program below shows how the copy constructor, move constructor, copy assignment operator, move assignment operator, and the destructor can be implemented including some other auxiliary functions.
#include <iostream>
#include <utility>
#include <functional>
#include <iterator>
template<typename T>
class List
{
private:
struct Node
{
T value;
Node *prev;
Node *next;
} *head = nullptr, *tail = nullptr;
void copy( const List &list )
{
if ( list.head )
{
head = tail = new Node { list.head->value, nullptr, nullptr };
for ( Node *current = list.head->next; current; current = current->next )
{
tail = tail->next = new Node { current->value, tail, nullptr };
}
}
}
public:
//! Default constructor
List() = default;
//! Copy constructor
List( const List &list )
{
copy( list );
}
// Constructor with iterators
template <typename InputIterator>
List( InputIterator first, InputIterator last )
{
if ( first != last )
{
head = tail = new Node { *first, nullptr, nullptr };
while ( ++first != last )
{
tail = tail->next = new Node { *first, tail, nullptr };
}
}
}
// Destructor
~List()
{
clear();
}
//! Move constructor
List( List &&list )
{
std::swap( head, list.head );
std::swap( tail, list.tail );
}
//! Copy assignment operator
List & operator =( const List &list )
{
clear();
copy( list );
return *this;
}
//! Move assignment operator
List & operator =( List &&list )
{
std::swap( head, list.head );
std::swap( tail, list.tail );
return *this;
}
void clear()
{
while ( head )
{
delete std::exchange( head, head->next );
}
tail = head;
}
void push_front( const T &value )
{
head = new Node{ value, nullptr, head };
if ( !tail )
{
tail = head;
}
else
{
head->next->prev = head;
}
}
void push_back( const T &value )
{
Node *new_node = new Node{ value, tail, nullptr };
if ( tail )
{
tail = tail->next = new_node;
}
else
{
head = tail = new_node;
}
}
friend std::ostream & operator <<( std::ostream &os, const List &list )
{
for ( Node *current = list.head; current; current = current->next )
{
os << current->value << " -> ";
}
return os << "null";
}
};
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> list1( std::begin( a ), std::end( a ) );
std::cout << list1 << '\n';
list1 = List<int>( std::rbegin( a ), std::rend( a ) );
std::cout << list1 << '\n';
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
For example in this statement
list1 = List<int>( std::rbegin( a ), std::rend( a ) );
there is used the move assignment operator.
Because List tracks the tail, you can call a function that adds items to the end of the list without the added overhead of iterating to the end of the list.
List(const List& lst) : head_(nullptr), tail_(nullptr)
{
Node * cur = lst.head_; //get first source item.
while (cur) // if there is a source item to copy
{
push_back(cur->value_); // stick the item on the end of this list
cur = cur->next_; // get next source item
}
}
where push_back looks something like
void push_back(T value)
{
Node * newnode = new Node(value, tail_, nullptr); //make and link new tail node
if (tail_)
{
tail_->next_ = newnode; // link in new node
}
else
{
head_ = newnode;
}
tail_ = newnode; // update tail
}
and Node picked up a new constructor to simplify insertion:
Node(T value,
Node * prev,
Node * next) : value_(value), prev_(prev), next_(next)
{
}
Note:
In the assignment operators,
tail_ = nullptr;
head_ = tail_;
cut the pointers to any data that was in the linked list, leaking those Nodes. You need to free these nodes before replacing them. The Copy and Swap Idiom (What is the copy-and-swap idiom?) makes this easy by using the copy construction and destruction of a local variable to automate the process.

Swap Adjacent nodes in a Linked List Only by Manipulating pointers

I am trying to swap the adjacent nodes of a linked list i.e.
1->2->3->4->5 becomes 2->1->4->3->5
My function is:
node * swapper(node * &head)
{
if (head == NULL || head->next == NULL) return head;
node * t = head;
head= head->next;
head->next = t;
t->next = head->next;
node *previous = head->next->next, *current = previous->next;
while (current!=NULL&&previous!=NULL)
{
node * t1 = current,*t2=previous;
current->next = previous;
previous->next = t1->next;
previous = t1->next;
current = previous->next;
}
return head;
}
I know it can be done by swapping values but I have to do it in Constant space and without swapping the values.
I can't find why my function is not working.
The first thing that I can notice is that you need to swap those two lines:
head->next = t;
t->next = head->next;
because you are saying head->next = t so you are losing the connection to the rest of the linked list.
Also, inside the loop. There are several mistakes:
1- You're changing the next of current before obtaining it in previous, which means you're losing the link (like above)
2- You're not connecting them to the nodes that are before them.
My five cents.:)
Here is a demonstrative program that shows how to write a recursive function.
#include <iostream>
#include <functional>
struct node
{
int data;
struct node *next;
} *head;
void push_front( node * &head, int x )
{
head = new node { x, head };
}
void display( node *head )
{
for ( node *current = head; current; current = current->next )
{
std::cout << current->data << ' ';
}
std::cout << std::endl;
}
node * swapper( node * &head )
{
if ( head && head->next )
{
node *tmp = std::exchange(head, head->next );
std::exchange( tmp->next, std::exchange( tmp->next->next, tmp ) );
swapper( head->next->next );
}
return head;
}
int main()
{
const int N = 10;
for ( int i = N; i != 0; ) push_front( head, --i );
display( head );
display( swapper( head ) );
}
The program output is the following
0 1 2 3 4 5 6 7 8 9
1 0 3 2 5 4 7 6 9 8
Take into account that not all compilers support function std::exchange. So you will need to write it yourself.:)
If to write the main the following way
int main()
{
const int N = 10;
for ( int i = N; i != 0; ) push_front( head, --i );
display( head );
for ( node **current = &head; *current && ( *current )->next; current = &( *current )->next )
{
swapper( *current );
}
display( head );
}
then the following interesting output can be obtained.:)
0 1 2 3 4 5 6 7 8 9
1 3 5 7 9 8 6 4 2 0
node * swapper(node * &head)
{
if (head == NULL || head->next == NULL) return head;
node * t = head;
head= head->next;
t->next = head->next;
head->next = t;
node *previous = head->next->next, *current,*parent=head->next;
while (previous&&(current = previous->next))
{
node * t1 = current,*t2=previous;
previous->next = t1->next;
current->next = previous;
parent->next= current;
previous = t2->next;
//current = previous->next;
parent=t2;
}
return head;
}