链表
两两交换链表中的节点
leetcode.24
- 链接leetcode.cn/problems/sw…
- 解题方法:画图
注意:节点的指向顺序 - leetcode解题代码
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
auto dummy = new ListNode(-1);
dummy->next = head;
for (auto p = dummy; p->next && p->next->next;){
auto a = p->next, b = a->next;
p->next = b;
a->next = b->next;
b->next = a;
p = a;
}
return dummy->next;
}
};
旋转链表
leetcode.61
- 链接leetcode.cn/problems/ro…
- 解题方法:画图
- leetcode解题代码
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (!head) return head;
int n = 0;
for (auto p = head; p; p = p->next) n ++;
k %= n;
if (k == 0) return head;
auto p = head;
for (int i = 0; i < n - k - 1; i ++) p = p->next;// 找到倒数第k+1个点
auto tail = head;
while (tail->next) tail = tail->next;// 找到尾节点
tail->next = head;// 尾节点指向旧的头节点
head = p->next;// 新的头节点
p->next = nullptr;// 新的尾节点指向空
return head;
}
};
反转链表
leetcode.206
- 链接leetcode.cn/problems/re…
- 解题方法:迭代,画图
- leetcode解题代码
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
auto a = head, b = head->next;
while (b){
auto c = b->next;
b->next = a;
a = b;
b = c;
}
head->next = nullptr;
return a;
}
};
- 解题方法:递归,递归的返回值为新头节点
- leetcode解题代码
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
auto p = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return p;
}
};
leetcode.92
- 链接leetcode.cn/problems/re…
- 解题方法:迭代
- leetcode解题代码
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
auto dummy = new ListNode(-1);
dummy->next = head;
auto p = dummy;
for (int i = 0; i < m - 1; i ++) p = p->next;// 找到第m-1个节点
// 将[m, n]反转与上一题迭代法相似
auto a = p->next, b = a->next;
for (int i = 0; i < n - m; i ++){
auto c = b->next;
b->next = a;
a = b;
b = c;
}
p->next->next = b;
p->next = a;
return dummy->next;
}
};
相交链表、环形链表
leetcode.160
- 链接leetcode.cn/problems/in…
- 解题方法:双指针+找规律
A段+B段+重合段的总长度相等
一个指针从A段向前遍历当遍历到结尾跳到B段开头
另一个指针从B段向前遍历当遍历到结尾跳到A段开头
由于两个指针走过的路程相等,移动速度也相等,所以必然在相交点相遇 - leetcode解题代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto p = headA, q = headB;
while (p != q){
if (p) p = p->next;
else p = headB;
if (q) q = q->next;
else q = headA;
}
return p;
}
};
leetcode.141
- 链接leetcode.cn/problems/li…
- 解题方法:快慢指针
一个指针每次向前移动一位,另一个指针每次向前移动两位
如果链表不存在环则两个指针永远不可能相遇 - leetcode解题代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if (!head || !head->next) return false;
auto fast = head, slow = head;
while (fast){
fast = fast->next, slow = slow->next;
if (fast){
fast = fast->next;
}
if (fast == slow) return true;
}
return false;
}
};
leetcode.142
- 链接leetcode.cn/problems/li…
- 解题方法:快慢指针+找规律
当两个指针相遇的时候,将一个指针指向头节点,另一个指针留在原地
令两个指针的移动速度相等,则再次相遇的位置就是环形入口 - leetcode解题代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (!head || !head->next) return NULL;
auto s = head, f = head;
while (f){
s = s->next, f = f->next;
if (f) f = f->next;
if (s == f){
s = head;
while (s != f){
s = s->next, f = f->next;
}
return s;
}
}
return NULL;
}
};
解题参考:www.acwing.com/