阅读更多文章,请看学习笔记汇总
链表题目汇总
链表题不难,只要你在纸上画个图就会很简单
。把思路模拟一遍,主要代码先写在纸上,不要急着敲代码。你会发现在纸上写一下,链表题会特别简单
如果找指向最后一个结点的指针,判断条件就用if (p->next != NULL)
。其实就看你希望到哪停止,条件就怎么设置
如果要往后走一步,我们先要判断当前结点是否为空;如果走两步就一次一次走,每次判断一下
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {} // 初始化列表法
};
ListNode* dummy = new ListNode(-1);
或
ListNode* dummy = new ListNode({-1,nullptr});
int n = 0;
for (auto p = head; p; p = p->next) n ++;
if(!head || !head->next) return head;
p->next = p->next->next;
p = p->next; (类似i++)
while(p->next) {
p = p->next;
}
计算结点数的方法:让一个指针再走一圈,回到相遇的位置
class Solution {
public:
bool hasCycle(ListNode *head) {
int cnt = 1;
auto fast = head, slow = head;
while(fast){
fast = fast->next;
slow = slow->next;
if (fast) fast = fast->next;
else return false;
// Counting junction points
if (fast == slow) {
auto tmp = fast;
fast = fast->next;
while(fast != tmp) {
fast = fast->next;
cnt ++;
}
cout << cnt << endl;
return true;
}
}
return false;
}
};
LeetCode上面的链表都是它事先创建好的,那如果我想自己创建一个链表,然后再去试验各种链表操作函数,则可以用如下代码模版
#include
#include
using namespace std;
// 定义链表结点
typedef struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
} ListNode;
// 创建单链表(返回头结点)
ListNode *create_linkedlist(initializer_list<int> lst) {
auto iter = lst.begin();
ListNode *head = lst.size() ? new ListNode(*iter++) : nullptr;
for (ListNode *cur = head; iter != lst.end(); cur = cur->next)
cur->next = new ListNode(*iter++);
return head;
}
// 单链表正向输出(递归)
void printList(ListNode *head) {
if (head == nullptr) return;
cout << head->val << " ";
printList(head->next);
}
// 单链表反向输出(递归)
void printReverse(ListNode *head) {
if (head == nullptr) return;
printReverse(head->next);
cout << head->val << " ";
}
// 删除单链表
void clear(ListNode *head) {
while (head) {
ListNode *del = head;
head = head->next;
delete del;
}
}
// 翻转链表
ListNode *reverseList(ListNode *head) {
auto a = head, b = head;
if (!a || !a->next) return a;
b = a->next;
while(b) {
auto c = b->next;
b->next = a;
a = b;
b = c;
}
head->next = NULL;
head = a;
return head;
}
int main() {
ListNode *head = create_linkedlist({1, 4, 5, 3, 2, 6, 7});
printList(head);
cout << endl;
printList(reverseList(head));
clear(head);
}
/**
* @Author: Wilson79
* @Datetime: 2019年12月28日 星期六 14:40:26
* @Filename: 2.两数相加.cpp
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
int t = 0;
auto res = new ListNode(-1); // 创建一个虚拟结点
auto q = res;
while(l1 || l2 || t) { // 加个t是解决5 + 5的情况
if (l1) {
t += l1->val;
l1 = l1->next;
}
if (l2) {
t += l2->val;
l2 = l2->next;
}
auto p = new ListNode(t % 10);
t /= 10;
q -> next = p;
q = p;
}
q->next = NULL;
return res->next;
}
};
// 2019年12月25日 星期三 21:51:19
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if (!head) return;
auto fast = head, slow = head;
// 找中点
// 1 2 [3] 4
// 1 2 [3] 4 5
while(fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
// slow 中点
// 翻转链表
auto a = slow;
auto b = slow->next;
while(b) {
auto c = b->next;
b->next = a;
a = b;
b = c;
}
// 1->2->3<-4
// 1->2->3<-4<-5
auto p = head, q = a;
while(p != q && p->next != q) {
auto t = q->next;
q->next = p->next;
p->next = q;
p = p->next->next;
q = t;
}
slow->next = NULL; // 最终链表尾结点
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
auto fast = head, slow = head;
// odd-even 快慢指针法找链表的中点
while(fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// Recursion
// 1 2 5 NULL
// 3 4 7 NULL
if (l1 == nullptr) return l2;
if (l2 == nullptr) return l1;
// 可以理解为递归函数已经给你做好了
if (l1->val < l2->val) {
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}
else {
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
return nullptr;
}
};
原题链接
时空复杂度要求较高,先用快慢指针找出中点,然后逆序后半段,再依次比较即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
// 1 2 3 3 2 1 NULL
if (!head || !head->next) return true;
auto fast = head, slow = head, p = head;
while(fast) {
slow = slow->next;
fast = fast->next;
if(!fast) break;
fast = fast->next;
}
// Now slow is the head of half Link
auto a = slow, b = slow;
b = a->next;
while(b) {
auto c = b->next;
b->next = a;
a = b;
b = c;
}
slow->next = NULL;
auto q = a;
while(q) {
if(p->val != q->val) return false;
p = p->next;
q = q->next;
}
return true;
}
};
此题思路很巧妙——快慢指针
/**
* 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) {
// use fast and slow points
auto fast = head, slow = head;
while(fast) {
fast = fast->next;
slow = slow->next;
if (fast != NULL) fast = fast->next;
else break;
if (fast == slow) {
slow = head;
while(fast != slow) {
fast = fast->next;
slow = slow->next;
}
return fast; // second time meet position
}
}
return NULL;
}
};
/**
* 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) return head;
auto a = head, b = head->next, c = head;
// 1 2 3 4 5 NULL
// 5 4 3 2 1 NULL
while(b) { // 画个图很清楚
c = b->next;
b->next = a;
a = b;
b = c;
}
head->next = NULL;
return a;
}
};
在I的基础上要求链表翻转从m到n的部分
在纸上画个图就很容易了
易错点:while的判断条件是b,不是b->next
原题链接
参考图例
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if (m == n) return head;
auto dummy = new ListNode(-1); // Reduced boundary discussion
dummy->next = head;
auto ft = dummy, sd = dummy;
for (int i = 0; i < m - 1; i ++) ft = ft->next;
for (int i = 0; i < n; i ++) sd = sd->next;
auto a = ft->next; // similar to I:head
auto d = sd->next; // similar to I:NULL
// Reverse Linked List template
auto b = a->next;
while(b != d) { // b->next is wrong, cause b = c after while;
auto c = b->next;
b->next = a;
a = b;
b = c;
}
// Connect the fore and aft
ft->next->next = b;
ft->next = sd;
return dummy->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
// 在纸上画图模拟后,特别简单
ListNode *dummy = new ListNode(-1);
dummy->next = head;
auto p = dummy;
while(p->next && p->next->next) {
auto a = p->next, b = p->next->next;
p->next = b;
a->next = b->next;
b->next = a;
p = a;
}
return dummy->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// create a visual Node whose next is head;
if(!head -> next) return NULL;
auto dummy = new ListNode(-1);
dummy -> next = head;
auto first = dummy, second = dummy;
while(n --) first = first -> next;
// let two points move together
while(first -> next) {
first = first -> next;
second = second -> next;
}
second -> next = second -> next -> next;
return dummy -> next; // 真正的头结点
// 为什么return head;不行,详见数据结构笔记
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
node -> val = node -> next -> val; // 5 change to 1
node -> next = node -> next -> next; // delete origin 1
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode *cur = head;
if (!cur || !cur -> next) return head;
while(cur -> next) { // cur 和 cur -> next 有区别
if( cur -> val == cur -> next -> val) {
cur -> next = cur -> next -> next;
} else {
cur = cur -> next;
}
}
return head;
}
};
// https://leetcode-cn.com/problems/rotate-list/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (!head) return head;
int n = 0;
for (ListNode *p = head; p; p = p->next) n ++;
k %= n;
// two points move together
auto first = head, second = head;
while(k --) first = first->next;
while(first -> next) {
first = first->next;
second = second->next;
}
// Draw a clear picture
first->next = head;
head = second->next;
second->next = NULL;
return head;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
auto dummy = new ListNode(-1);
dummy->next = head;
auto a = dummy, b = dummy;
// draft in the paper first
while(b) {
b = a->next;
while(b && b->val == val) {
b = b ->next;
}
// delete val
a->next = b;
a = b;
}
return dummy->next;
}
};
算法:
1.Two pointers do not intersect
p and q both move a+b step, then turn into NULL.
2.Two pointers intersect
p adn q both move a+b+c step, then they will meet.
/**
* 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) {
// p and q both move a + b + c
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;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
// Nice, AC this problem only one attempt
// 1 4 3 2 5 2 x = 3
auto dummy1 = new ListNode(-1);
auto dummy2 = new ListNode(-1);
auto less = dummy1, greater = dummy2, p = head;
// less:dummy1->1->2->2 greater:dummy2->4->3->5
while(p) {
if (p->val < x) {
less->next = p;
less = less->next;
} else {
greater->next = p;
greater = greater->next;
}
p = p->next;
}
// Merge two lists
less->next = dummy2->next;
greater->next = NULL;
return dummy1->next;
}
};