常用操作
class MyLinkedList{public: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* head;int cnt;MyLinkedList(){cnt = 0;head = nullptr;}int get(int index){if(index<0 || index>=cnt) return -1;ListNode *p = head;while(p){if(index-- == 0) return p->val;p = p->next;}}void addAtHead(int val){ListNode* p = new ListNode(val);p->next = head;head = p;cnt++;}void addAtTail(int val){cnt++;if(!head){head = new ListNode(val);return ;}ListNode* p = head;while(p->next){p = p->next;}p->next = new ListNode(val);return ;}void addAtIndex(int index, int val){if(index>cnt) return;if(index<=0){addAtHead(val);return ;}if(index == cnt){addAtTail(val);return ;}ListNode* p = head;cnt++;while(p->next){if(--index == 0){p->next = new ListNode(val,p->next);return ;}p = p->next;}return ;}void deleteAtIndex(int index){if(index<0 || index>=cnt) return ;cnt--;if(index == 0){head = head->next;return ;}ListNode* p = head;while(p->next){if(--index == 0){p->next = p->next->next;return ;}p = p->next;}}void pfList(){cout<<"cnt:"<<cnt<<endl;ListNode* p = head;while(p){cout<<p->val<<' ';p = p->next;}cout<<endl;return ;}};
翻转链表
class Solution {public:ListNode* reverseList(ListNode* head) {ListNode* p = head;ListNode* post;ListNode* pre = nullptr;while(p) {post = p->next;p->next = pre;pre = p;p = post;}head = pre;return head;}};
删除倒数第n个节点(双指针法+哑巴节点)
class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummy = new ListNode(0, head);ListNode* first = head;ListNode* second = dummy;for (int i = 0; i < n; ++i) {first = first->next;}while (first) {first = first->next;second = second->next;}second->next = second->next->next;ListNode* ans = dummy->next;delete dummy;return ans;}};
链表相交
注意相交的节点之后都是同一节点了,也就是后面的都合并了
一种做法是统计长度,然后从短的开始同时遍历,还有一种比较巧妙的解法是a+c+b+c=b+c+a+c:
class Solution {public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* h1 = headA;ListNode* h2 = headB;while(h1 != h2){h1 = (h1 == nullptr ? headB : h1->next);h2 = (h2 == nullptr ? headA : h2->next);}return h1;}};
环形链表
可以使用快慢指针法, 分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。因为如果有环的话,相当于fast一个节点一个节点地追slow。
如何找到环的入口点?fast和slow相遇后的点设为index1,链表起始点设为index2,index1和2继续往后遍历必相遇,这时的相遇点就是环的入口。
class Solution {public:ListNode *detectCycle(ListNode *head) {ListNode* fast=head;ListNode* slow=head;while(fast && fast->next) {fast = fast->next->next;slow = slow->next;if(fast == slow) {ListNode* index1 = fast;ListNode* index2 = head;while(index1!=index2) {index1 = index1->next;index2 = index2->next;}return index1;}}return nullptr;}};
