链表
单链表 双链表 循环链表
链表_stl-CSDN博客
虚拟头结点
反转链表
删除链表元素
方法一: 直接使用原来的链表来进行删除操作。
头节点是否为空
头链表的值是否为要删除的值
头结点删除后,新的头节点是否依旧要删除 ,删除后的,新头节点可能是空结点
方法二: 设置一个虚拟头结点在进行删除操作。
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点dummyHead->next = head; // 将虚拟头结点指向head,这样方便后面做删除操作ListNode* cur = dummyHead;while (cur->next != NULL) {if(cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}head = dummyHead->next;delete dummyHead;return head;}
设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除
203. 移除链表元素 - 力扣(LeetCode)
// 危险操作!
1.直接操作原始头指针
2.造成空指针解引用 (先访问
head->val会触发尸变)
3.需要确保在删除节点后立即更新指针,避免悬空指针的使用
反转链表
206. 反转链表 - 力扣(LeetCode)
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode*cur=head;ListNode*pre=nullptr;ListNode*next;while(cur){next=cur->next;cur->next=pre;pre=cur;cur=next;}return pre;}
};
递归
( 从后往前翻转指针指向 )
ListNode* reverseList(ListNode* head) {// 递归终止条件if (!head || !head->next) {return head;}ListNode* reversedHead = reverseList(head->next);head->next->next = head;head->next = nullptr;return reversedHead;}
快慢指针 删除链表的倒数第N个节点
思想
如果要删除倒数第n个节点,让fast移动n+1步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了
为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作)
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode*dummy=new ListNode(0);dummy->next=head;ListNode*fast=dummy;ListNode*slow=dummy;for(int i=0;i<n+1;i++){fast=fast->next;}while(fast){slow=slow->next;fast=fast->next;}ListNode*temp=slow->next;slow->next=temp->next;delete temp;return dummy->next;}
};
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
链表相交
简单来说,就是求两个链表交点节点的指针
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode*currentA=headA;ListNode*currentB=headB;int lenA=0,lenB=0;while(currentA){currentA=currentA->next;lenA++;}while(currentB){currentB=currentB->next;lenB++;}currentA=headA;currentB=headB;if(lenA>lenB){int len=lenA-lenB;while(len--){currentA=currentA->next;}}if(lenA<lenB){int len=lenB-lenA;while(len--){currentB=currentB->next;}}while(currentA!=currentB){currentB=currentB->next; currentA=currentA->next;}return currentA;}
};
面试题 02.07. 链表相交 - 力扣(LeetCode)
环形链表II
fast走两步,slow走一步,相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合
在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。
让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点
(x + y) * 2 = x + y + n (y + z)
x + y = n (y + z)
x = n (y + z) - y
x = (n - 1) (y + z) + z
当 n为1的时候,公式就化解为 x = z
这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode*show=head;ListNode*fast=head;while(fast != NULL && fast->next != NULL){show=show->next;for(int i=0;i<2;i++)fast=fast->next;if(show==fast){ListNode*index1=head;ListNode*index2=fast;while(index1!=index2){index1=index1->next;index2=index2->next;}return index1;}}return nullptr;}
};
142. 环形链表 II - 力扣(LeetCode)