链表

Posted by Liao on 2020-02-05

初始化一个结点

1
2
3
4
ListNode node = new ListNode();  //初始化一个空结点,无值(不提倡这样写)

ListNode node = new ListNode(0); //初始化一个节点值为0的空结点(最常用的规范写法)

手动建链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// #include <bits/stdc++.h>
#include <iostream>
using namespace std;

struct ListNode {
int val;
ListNode *next;
explicit ListNode(int x) : val(x), next(nullptr) {}
// 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 == nullptr){
return head;
}
else if(head->next == nullptr){
return head;
}
ListNode* prev = nullptr;
ListNode* curr;
while(head != nullptr){
curr = head;
head = head->next;
curr->next = prev;
prev = curr;
}
return prev;
}
};

int main(){
ListNode n1(0);
ListNode n2(2);
ListNode n3(5);
ListNode n4(7);
ListNode n5(10);
n1.next = &n2;
n2.next = &n3;
n3.next = &n4;
n4.next = &n5;
ListNode* head = &n1;
while(head){
cout << head->val << ' ';
head = head->next;
}

Solution so;
so.reverseList(&n1);
cout << endl;

head = &n5;
while(head){
cout << head->val << ' ';
head = head->next;
}

return 0;
}

Leetcode 21 合并两个有序链表

输入:1->2->4, 1->3->4

输出:1->1->2->3->4->4

比较l1 l2结点值的大小,如果l1<= l2,则把l1的结点装在新链表p中,并把l1指针后移。p指向下一个结点。

指针移动之后,到目前的l1和l2比较,显然l2结点比较大,于是把l2放在p链表,l2链表指向下一个结点。

如此类推……

直到指针指向NULL时,(跳出了循环)把另外一个链表剩下的结点拼接到链表p就行(因为链表都是有序的),-再返回head->next就能把合并出来的新链表返回。

迭代版代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *head = new ListNode(0);
ListNode *p = head;

while(l1 != NULL && l2 != NULL)
{
if(l1->val <= l2->val)
{
p -> next = l1; //在新链表上插入值
l1 = l1 -> next; //原链表指针指向下一个
}
else
{
p -> next = l2;
l2 = l2 -> next;
}
p = p -> next;
}
if(l1 != NULL)
p -> next = l1;
if(l2 != NULL)
p -> next = l2;

return head->next;
}

递归版代码:(时间复杂度和空间复杂度相对比迭代的少)

1
2
3
4
5
6
7
8
9
10
11
12
13
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2){
if (!list1) {
return list2;
} else if (!list2) {
return list1;
} else if (list1->val < list2->val) {
list1->next = mergeTwoLists(list1->next, list2);
return list1;
} else {
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}

反转链表

反转单链表

输入: 1->2->3->4->5->NULL

输出: 5->4->3->2->1->NULL

NULL->1->2->3->4->5->NULL

用迭代的方法解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct ListNode{
int val;
ListNode *next;
ListNode(int x): val(x),next(NULL) {}
};
ListNode* reverseList(ListNode* head) {
if(head == NULL)
return NULL;
ListNode *p0 = NULL;
ListNode *p1 = head;
ListNode *p2 = head->next;

while(p1 != NULL)
{
p1 -> next = p0; //反转指向
p0 = p1; //指针前进
p1 = p2; //指针前进
if(p2 != NULL)
p2 = p2->next;
}
return p0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//另一种更简便的方法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur = NULL, *pre = head;
while (pre != NULL) {
ListNode* t = pre->next;
pre->next = cur; //指针翻转
cur = pre;
pre = t;
}
return cur;
}
};

用递归方法解决:

1
2
3
4
5
6
7
8
ListNode* reverseList(ListNode* head) {
if(head == NULL|| head->next == NULL)
return head;
ListNode *newhead = reverseList(head->next);//把新头结点递归到链表的最后一个元素,从后往前翻转。
head->next->next = head; //后一个结点指向前一个结点
head->next = NULL; //断了前一个结点指向后一个节点的关系
return newhead;
}

返回链表倒数第k个节点

双指针解法:

1
2
3
4
5
6
7
8
9
10
11
12
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode *p,*q;
p = head, q = head;
while(k--){
p = p->next;
}
while(p){
p = p->next;
q = q->next;
}
return q;
}