链表类问题
基础链表题目
206. 反转链表
使用双指针法解决链表问题
19. 删除链表的倒数第N个节点
用两个指针指向head节点,先让第一个指针走n-1步,然后再让两个指针同时走,直到第一个指针的next为nullptr,此时第二个指针指向的就是要删除的节点。这里为了减少不必要的判断,我们把第二个指针设为二级指针。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pfirst = head;
ListNode** psecond = &head;
for (int i = 1;i < n;++i) {
pfirst = pfirst->next;
}
while (pfirst->next) {
psecond = &(*psecond)->next;
pfirst = pfirst->next;
}
*psecond = (*psecond)->next;
return head;
}
};
160. 相交链表
先遍历两个链表获取它们的长度lenA和lenB,然后先让指针ptrA在长链表(假设长链表是A,短链表是B)上走lenA - lenB步,再让指针ptrA和ptrB分别在长链表和短链表上移动,二者相遇时就是交叉点。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = getLength(headA);
int lenB = getLength(headB);
if (lenA > lenB) {
for (int i = 0;i < lenA - lenB;++i) {
headA = headA->next;
}
} else {
for (int i = 0;i < lenB - lenA;++i) {
headB = headB->next;
}
}
while (headA && headB) {
if (headA == headB) {
return headA;
} else {
headA = headA->next;
headB = headB->next;
}
}
return nullptr;
}
private:
int getLength(ListNode* head) {
int len = 0;
while (head) {
++len;
head = head->next;
}
return len;
}
};
使用二级指针操作链表
2. 两数相加
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
auto p1 = l1;
auto p2 = l2;
ListNode* ph = nullptr;
ListNode** curr = &ph;
int carry = 0;
while (p1 || p2) {
int x = p1 ? p1->val : 0;
int y = p2 ? p2->val : 0;
int val = x + y + carry;
carry = val / 10;
val = carry ? val - 10 : val;
*curr = new ListNode(val);
curr = &(*curr)->next;
if (p1) p1 = p1->next;
if (p2) p2 = p2->next;
}
if (carry) *curr = new ListNode(1);
return ph;
}
};
LeetCode 21. 合并两个有序链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head = nullptr;
ListNode** curr = &head;
auto p1 = l1;
auto p2 = l2;
while (p1 && p2) {
if (p1->val < p2->val) {
*curr = p1, p1 = p1->next;
} else {
*curr = p2, p2 = p2->next;
}
curr = &(*curr)->next;
}
if (p1) *curr = p1;
if (p2) *curr = p2;
return head;
}
};
相似题目
23. 合并K个有序链表
21题的进阶版,每次迭代,分别合并链表数组中第一个和最后一个链表,当数组中仅剩一个链表时退出,均摊时间复杂度为\(O(n\log n)\)。
148. 排序链表
重新排列链表
86. 分隔链表
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* newHead = nullptr;
ListNode** prev = &newHead;
for (auto iter = &head; *iter;) {
if ((*iter)->val < x) {
*prev = *iter;
prev = &(*prev)->next;
*iter = (*iter)->next;
} else {
iter = &(*iter)->next;
}
}
*prev = head;
return newHead;
}
};
相关题目:
328. 奇偶链表
链表与其他数据结构的结合
138. 复制带随机指针的链表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
Node* pHead = head;
while (head) {
randomMap[head] = new Node(head->val);
head = head->next;
}
Node* newHead = randomMap[pHead];
Node* qHead = newHead;
while (qHead && pHead) {
qHead->next = randomMap[pHead->next];
qHead->random = randomMap[pHead->random];
pHead = pHead->next;
qHead = qHead->next;
}
return newHead;
}
private:
unordered_map randomMap;
};