24. 两两交换链表中的节点
leetcode题目链接
思路:遍历链表,进行两两交换的操作。
注意的点:
- 遍历的点指在哪里(必须指在两两交换的前一个节点)
- 遍历终止的条件是什么
- 两两操作的逻辑
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode *tmp = head;
ListNode *prev = dummyhead;
while (tmp && tmp->next) {
ListNode *next = tmp->next->next;
tmp->next->next = tmp;
prev->next = tmp->next;
tmp->next = next;
prev = tmp;
tmp = next;
}
return dummyhead->next;
}
};
19.删除链表的倒数第N个节点
leetcode题目链接
定义一个快指针和一个慢指针,快指针比慢指针快n步,然后当快指针的next指向NULL时,也就是慢指针指向要被删除的元素的前一个。进行删除操作即可。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
for (int i = 0; i < n; ++i) {
fast = fast->next;
}
while (fast->next) {
fast = fast->next;
slow = slow->next;
}
ListNode *deleted = slow->next;
slow->next = deleted->next;
delete(deleted);
return dummyhead->next;
}
};
面试题 02.07. 链表相交
leetcode题目链接
求出两个链表的长度,一个指针指向短的链表头节点,另一个指向长链表+两链表长度差的节点,然后判断指针是否相同。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int len1 = 0, len2 = 0;
ListNode *n1 = headA;
ListNode *n2 = headB;
while (n1) {
len1++;
n1 = n1->next;
}
while (n2) {
len2++;
n2 = n2->next;
}
n1 = headA;
n2 = headB;
if (len1 > len2) {
int tmp = len1;
len1 = len2;
len2 = tmp;
ListNode *tmpn = n1;
n1 = n2;
n2 = tmpn;
}
int distance = len2 - len1;
while (distance--) {
n2 = n2->next;
}
while (n1) {
if (n1 == n2)
return n1;
n1 = n1->next;
n2 = n2->next;
}
return NULL;
}
};
142.环形链表II
leetcode题目链接
怎么判断链表是否有环形呢?设置一个快指针,一个慢指针,快指针每次走两步,慢指针每次走一步,如果两个指针会相遇,那么存在环形链表。
怎么找到环形链表入口呢?具体证明过程不写了,操作过程如下:
- 同样是快慢指针,记录下两指针相遇的节点。
- 定义另一个指针从头节点开始,一个从相遇节点开始,都是一步一步走,相遇的地方就是环形链表入口。
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 *intersection = fast;
ListNode *tmp = head;
while (intersection != tmp) {
intersection = intersection->next;
tmp = tmp->next;
}
return intersection;
}
}
return NULL;
}
};
总结
虚拟链表使用场景一般是头节点情况需要单独处理的情况,也就是插入、删除节点的场景。