[learning notes] [Leetcode explanation by category] - linked list

Posted by daxxy on Tue, 04 Jan 2022 05:04:06 +0100

The chain list problem is very easy to make mistakes. Please be sure to draw the process on the paper first. Please tear it by hand and draw a schematic diagram
Virtual head node + iteration + recursion

2. Storage mode of linked list: the nodes of the linked list are stored in memory in a decentralized manner and connected together through pointers.
4. Performance analysis of array and linked list in different scenarios.

0. A topic examines the five common operations of the linked list! ​

If you don't understand it, it will be annoying (recursion), and if you understand it, it will be great (head insertion)

——Method 1: three pointer iteration: flip the current node and save the next node and the previous node class Solution {
public:
while(cur!=nullptr){
ListNode *tmp = cur->next;//Save cur - > next
cur->next = pre;//reverse
pre = cur;//Go back
cur = tmp;//cur, go back
}
return pre;//At the end of the cycle, cur comes to the end, so return pre
}
};

——Method 2: recursion Detailed PPT diagram

class Solution {
public:
//The recursive termination condition is that the current node is empty or the next node is empty
}
//cur here is the last node
ListNode *cur = reverseList(head->next);//Recurse until the termination condition is triggered
head->next->next = head;//If the linked list is 1 - > 2 - > 3 - > 4 - > 5, then the cur is 5 / / and the head is 4, the next head is 5, and the next head is empty
head->next = nullptr;//To prevent the linked list from circulating, you need to set the head Next is set to null
return cur;//Each recursive function returns cur, which is the last node
}
};

[92. Reverse linked list II] - wonderful, extremely wonderful!

class Solution {
public:
ListNode *pre = nullptr;
while(cur!=nullptr){
ListNode *Next = cur->next;
cur->next = pre;
pre = cur;
cur = Next;
}
return pre;
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *dummyHead = new ListNode(-1);//This can't be nullptr
for(int i = 0;i<left-1;i++){pre = pre->next;}//Find pre for left
ListNode *LeftNode = pre -> next;
ListNode *RightNode = pre;//Use the following loop to find the RightNode
for(int i = 0;i<right-left+1;i++){RightNode = RightNode->next;}
ListNode *curr = RightNode->next;//Record rightnode - > next first! Or I won't find it
RightNode -> next = nullptr;//Truncate head and tail
pre->next = nullptr;
reverseList(LeftNode);//reverse requirements
pre->next = RightNode;//Resume the head and tail
LeftNode->next = curr;
}
};

——Method 2: head insertion! Wonderful, wonderful!

Look at the picture

class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *dummyHead = new ListNode(-1);//It can't be nullptr here. It can be 0 or - 1 in parentheses
for(int i = 0;i<left-1;i++){pre = pre->next;}
ListNode *leftNode = pre->next;
for(int i = 0;i<right-left;i++){//Take the value = 2 at left as an example
ListNode *remove = leftNode->next;//Record the original next position 3
leftNode->next = leftNode->next->next;//2 points to next 2 - > 4 of 3
remove->next = pre->next;//3->2
pre->next = remove;//1->3
//After the first round, it becomes 1 - > 3 - > 2 - > 2 - > 4
}
}
}; ——There are two ways to delete problems: iteration and recursion

dummy is used to solve the problem, so there is no need to consider one more head node problem;
In an iterative manner.

public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *dummy = new ListNode(-1);
ListNode *tail = dummy;
while(tail ->next){//Even if the list of questions brush less, not skilled
if(tail ->next ->val ==val){tail->next = tail->next->next;}
else{tail = tail->next;}
}
return dummy->next;
}
};

[82. Delete duplicate Element II in the sorting linked list]

There is a linked list arranged in ascending order. Give you the head node of the linked list. Please delete all nodes with duplicate numbers in the linked list and only keep the numbers that do not appear repeatedly in the original linked list.

Returns a linked list of results in the same ascending order.
Output: [1,2,5]

Basic ideas
Almost all linked list problems have similar problem-solving ideas.
1. Create a dummy header node to reduce boundary judgment, and the subsequent answer list will be followed by dummy
2. Use tail to represent the end of the currently valid linked list

We will ensure that "when entering the outer loop, the head will not be the same as the previous node", so the insertion time:
1. There is no next node in the head. The head can be inserted
2.head has the following node, but the value is different from that of head. Head can be inserted

class Solution {
public:
auto dummy = new ListNode(-1),tail = dummy;
}
}
tail->next = nullptr;//You can't forget if you point to the empty space behind the tail
return dummy->next;
}
};

[83. Delete duplicate elements in the sorting linked list]

Output: [1,2]

class Solution {
public:
ListNode* dummy = new ListNode(109);
ListNode* tail = dummy;
}
}
tail->next = nullptr;
return dummy->next;
}
};

Give you a head node of the linked list and a specific value X. please separate the linked list so that all nodes less than x appear before nodes greater than or equal to X.
You should keep the initial relative position of each node in both partitions. Then the two nodes go through the needle and make the small and large list

class Solution {
public:
ListNode* partition(ListNode* head, int x) {//Two virtual head nodes, smallhead and Bighead, are required, and then the two nodes go through the needle to fix the small and large list s,
}
else{
}
}
big->next = nullptr;
}
};

[21. Merge two ordered linked lists]

Merge the two ascending linked lists into a new ascending linked list and return. The new linked list is composed of all nodes of a given two linked lists. Idea: it's comparison. Note that there are empty points after comparing a list. At this time, the following two while should be added!!!

class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(-1);
ListNode* tail = dummy;
if(!l1 and !l2) return nullptr;
if(!l1 and l2)  return l2;
if(l1 and !l2)  return l1;
while(l1 and l2){
if(l1->val <= l2->val){
tail->next = l1;
tail = l1;
l1 = l1->next;
}
else{
tail->next = l2;
tail = l2;
l2 = l2->next;
}
}
while(l1){
tail->next = l1;
tail = l1;
l1 = l1->next;
}
while(l2){
tail->next = l2;
tail = l2;
l2 = l2->next;
}
tail->next = nullptr;
return dummy->next;
}
};

class Solution {
public:
ListNode *dummyHead = new ListNode (-1);
ListNode *even = evenHead;//Move with even
while(even!=nullptr && even->next!=nullptr){//Update conditions should be judged well
even = even ->next;
}
}
}; Idea:
1. Save Val of l1 and l2 with a and b respectively (judge whether they exist or not first)
2. Save carry with t
3.cur to store the current value (perhaps sum is better)
4. Update

class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *dummy = new ListNode(0);
ListNode *cur = dummy;
int t = 0;
while(l1 or l2){
int a = l1?l1->val:0;
int b = l2?l2->val:0;
t = a+b+t;
cur -> next = new ListNode(t%10);
t /= 10;
cur = cur->next;
if(l1) l1 = l1->next;
if(l2) l2 = l2->next;
}
if(t!=0) cur ->next = new ListNode(t);
return dummy->next;
}
};

Idea:
Here is to change the direction. It is required not to reverse, so stack is the best. Push all the numbers into the stack, and then take them out and add them in turn. Attention should be paid to carry during calculation. Finally get the answer. It's wonderful. It's a bit like head insertion.

class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1,s2;
while(l1) {s1.push(l1->val);l1 = l1->next;}
while(l2) {s2.push(l2->val);l2 = l2->next;}
int t = 0;//carry
ListNode *tail = nullptr;//For back reversal
while(!s1.empty() or !s2.empty() or t!=0){//Attention t= 0 should also be placed as a condition
int a = s1.empty()?0:s1.top();
int b = s2.empty()?0:s2.top();
if(!s1.empty()) s1.pop();
if(!s2.empty()) s2.pop();
int cur = (a+b+t)%10;//return val of the linked list
t = (a+b+t)/10;//Update carry
ListNode *curnode = new ListNode(cur);//Open a new curnode to put the val of cur
curnode ->next = tail;//Draw a picture to understand the reversal here, which is very similar to the head interpolation
tail = curnode;
}
return tail;
}
};

[24. Exchange nodes in linked list in pairs] FN: node1 CN: node2 n: next

class Solution {
public:
ListNode* dummy = new ListNode(0);
ListNode* pre = dummy;
while(pre->next && pre->next->next){
ListNode* FN = pre->next;
ListNode* CN = FN ->next;
ListNode* n = CN->next;

CN ->next = FN;
FN ->next = n;
pre->next = CN;

pre = FN;
}
return dummy->next;
}
};

4. Double pointer

[19. Delete the penultimate node of the linked list] class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(-1);
ListNode* fast = dummy;
ListNode* slow = dummy;
while(n-- && fast!=nullptr){fast =fast->next;}
fast = fast->next;
while(fast!=nullptr){
fast = fast->next;
slow = slow->next;
}
ListNode* del_node = slow->next;//C + + features, to learn to free memory
slow->next = del_node->next;
delete del_node;
return dummy->next;
}
};

Topics: Algorithm data structure