链表 | ||
1. 找出两个链表的交点 | 第一次可做出, 解法可优化 | ※ |
2. 链表反转 | 递归/迭代 两种方法 | ※ |
3. 归并两个有序的链表 | 可做出 经典题型,两种方法需掌握 | ※ |
4. 从有序链表中删除重复节点 | 第一次可做出Ok |
|
5. 删除链表的倒数第 n 个节点 | 第一次可做出Ok |
|
6. 交换链表中的相邻结点 | 思考后可做出 解法可简化 | ※ |
7. 链表求和 | 第一次未做出 | ※ |
8. 回文链表 | 思考后可做出 解法可简化 | ※ |
9. 分隔链表 | 思考后可做出Ok |
|
10. 链表元素按奇偶聚集 | 思考后可做出 |
|
链表是空节点,或者有一个值和一个指向下一个链表的指针,因此很多链表问题可以用递归来处理。
1. 找出两个链表的交点
160. Intersection of Two Linked Lists (Easy)
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
法一:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pa=headA,*pb=headB;
while(pa!=NULL||pb!=NULL){
if(pa==NULL) headB=headB->next;
else pa=pa->next;
if(pb==NULL) headA=headA->next;
else pb=pb->next;
}
while(headA!=headB){
headA=headA->next;
headB=headB->next;
}
return headB;
}
};
法二:技巧性强
当访问 A 链表的指针访问到链表尾部时,令它从链表 B 的头部开始访问链表 B;同样地,当访问 B 链表的指针访问到链表尾部时,令它从链表 A 的头部开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访问到交点。
/**
* 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) {
ListNode *pa=headA,*pb=headB;
while(pa!=pb){
pa=(pa==NULL)?headB:pa->next;
pb=(pb==NULL)?headA:pb->next;
}
return pa;
}
};
2. 链表反转
206. Reverse Linked List (Easy)
https://leetcode-cn.com/problems/reverse-linked-list/
1. 递归
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL||head->next==NULL) return head;
ListNode *hn=reverseList(head->next);
head->next->next=head;
head->next=NULL;
return hn;
}
};
2. 迭代
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *ph=head,*res=NULL;
while(ph!=NULL){
ListNode* pn=ph->next;
ph->next=res;
res=ph;
ph=pn;
}
return res;
}
};
3. 归并两个有序的链表
21. Merge Two Sorted Lists (Easy)
https://leetcode-cn.com/problems/merge-two-sorted-lists/
1. 递归
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL||l2==NULL) return (l1==NULL)?l2:l1;
if(l1->val<l2->val){
l1->next=mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next=mergeTwoLists(l1,l2->next);
return l2;
}
}
};
2. 迭代
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *l=new ListNode(-1),*pl=l;
while(l1!=NULL&&l2!=NULL){
if(l1->val<l2->val){
pl->next=new ListNode(l1->val);
l1=l1->next;
}else{
pl->next=new ListNode(l2->val);
l2=l2->next;
}
pl=pl->next;
}
pl->next=(l1==NULL)?l2:l1;
return l->next;
}
};
4. 从有序链表中删除重复节点
83. Remove Duplicates from Sorted List (Easy)
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/
5. 删除链表的倒数第 n 个节点
19. Remove Nth Node From End of List (Medium)
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
6. 交换链表中的相邻结点
24. Swap Nodes in Pairs (Medium)
https://leetcode-cn.com/problems/swap-nodes-in-pairs/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *res=new ListNode(-1),*prev=res;
res->next=head;
while(prev->next!=NULL&&prev->next->next!=NULL){
ListNode *pl=prev->next,*ph=prev->next->next;
pl->next=ph->next;
ph->next=pl;
prev->next=ph;
prev=pl;
}
return res->next;
}
};
7. 链表求和
445. Add Two Numbers II (Medium)
https://leetcode-cn.com/problems/add-two-numbers-ii/
class Solution {
public:
stack<int> buildStack(ListNode* l){
stack<int> st;
while(l!=NULL){
st.push(l->val);
l=l->next;
}
return st;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> st1=buildStack(l1);
stack<int> st2=buildStack(l2);
ListNode* res=new ListNode(-1);
int carry=0;
while(!st1.empty()||!st2.empty()||carry){
if(!st1.empty()){
carry+=st1.top();
st1.pop();
}
if(!st2.empty()){
carry+=st2.top();
st2.pop();
}
ListNode *pn=new ListNode(carry%10);
pn->next=res->next;
res->next=pn;
carry/=10;
}
return res->next;
}
};
8. 回文链表
234. Palindrome Linked List (Easy)
https://leetcode-cn.com/problems/palindrome-linked-list/
题目要求:以 O(1) 的空间复杂度来求解。
切成两半,把后半段反转,然后比较两半是否相等。
class Solution {
public:
ListNode* reverseList(ListNode* head){
ListNode *rev=NULL;
while(head!=NULL){
ListNode *nt=head->next;
head->next=rev;
rev=head;
head=nt;
}
return rev;
}
bool isPalindrome(ListNode* head) {
ListNode *slow=head,*fast=head;
while(fast!=NULL&&fast->next!=NULL){
slow=slow->next;
fast=fast->next->next;
}
ListNode *last=reverseList(slow);
while(last!=NULL){
if(head->val!=last->val) return false;
head=head->next;
last=last->next;
}
return true;
}
};
9. 分隔链表
725. Split Linked List in Parts(Medium)
https://leetcode-cn.com/problems/split-linked-list-in-parts/
10. 链表元素按奇偶聚集
328. Odd Even Linked List (Medium)
https://leetcode-cn.com/problems/odd-even-linked-list/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(head==NULL) return NULL;
ListNode *odd=head,*even1=head->next,*even2=even1;
while(even2!=NULL&&even2->next!=NULL){
odd->next=even2->next;
even2->next=even2->next->next;
odd=odd->next;
odd->next=even1;
even2=even2->next;
}
return head;
}
};