Linked list related summary
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
- The main types of linked lists are: single linked list, double linked list and circular linked list
- Storage mode of linked list: the nodes of the linked list are stored in memory in a decentralized manner and connected together through pointers.
- How to add, delete, modify and query the linked list.
- Performance analysis of array and linked list in different scenarios.
0. A topic examines the five common operations of the linked list!
1. Linked list problem - threading, head inserting method
If you don't understand it, it will be annoying (recursion), and if you understand it, it will be great (head insertion)
[206. Reverse linked list]
——Method 1: three pointer iteration: flip the current node and save the next node and the previous node
class Solution { public: ListNode* reverseList(ListNode* head) { ListNode *pre = nullptr;//dummyHead ListNode *cur = head; 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
class Solution { public: ListNode* reverseList(ListNode* head) { //The recursive termination condition is that the current node is empty or the next node is empty if(head == nullptr||head->next == nullptr){ return head; } //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!
——Method 1: Threading
class Solution { public: ListNode *reverseList(ListNode *head){ ListNode *pre = nullptr; ListNode *cur = head; 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 dummyHead->next = head; ListNode *pre = dummyHead; 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; return dummyHead->next; } };
——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 dummyHead->next = head; ListNode *pre = dummyHead; 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 } return dummyHead->next; } };
[203. Remove linked list elements]
——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); dummy ->next = head; 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.
Input: head = [1,2,3,3,4,4,5]
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
3. Scan the linked list through the original head pointer
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: ListNode* deleteDuplicates(ListNode* head) { auto dummy = new ListNode(-1),tail = dummy; while(head){ if(head->next == nullptr or head->val != head->next->val){ tail->next = head; tail = head; } while(head->next and head->val == head->next->val) head = head->next; head = head->next; } 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]
Input: head = [1,1,2]
Output: [1,2]
class Solution { public: ListNode* deleteDuplicates(ListNode* head) { ListNode* dummy = new ListNode(109); ListNode* tail = dummy; while(head){ if(tail->val!=head->val){ tail->next = head; tail = head; } head = head->next; } tail->next = nullptr; return dummy->next; } };
[86. Separate linked list]
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.
——Set up two virtual head nodes smallHead bigHead
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, ListNode* smallHead = new ListNode(0); ListNode* small = smallHead; ListNode* bigHead = new ListNode(0); ListNode* big = bigHead; while(head){ if(head->val<x){ small->next = head; small = head; } else{ big->next = head; big = head; } head = head->next; } small->next = bigHead->next;//This is the function of bigHead big->next = nullptr; return smallHead->next; } };
[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; } };
[328. Parity linked list]
class Solution { public: ListNode* oddEvenList(ListNode* head) { if(head==nullptr) return head; ListNode *dummyHead = new ListNode (-1); dummyHead->next = head; ListNode *evenHead = head->next;//Mark the node of even t ListNode *even = evenHead;//Move with even while(even!=nullptr && even->next!=nullptr){//Update conditions should be judged well head ->next = even ->next; head = head ->next; even ->next = head ->next; even = even ->next; } head ->next = evenHead; return dummyHead->next; } };
[2. Add two numbers]
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; } };
[445. Adding two numbers II]
——stack + head insertion method
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* swapPairs(ListNode* head) { ListNode* dummy = new ListNode(0); dummy->next = head; 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; } };
2. Linked list sorting problem (to be done)
[147. Insert and sort linked list]
[148. Sorting linked list]
3. It's not just a linked list problem
[237. Delete nodes in the linked list]
——Introduce C + + memory management and design principles (not very understood) link
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); dummy ->next = head; 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; } };