Skip to content

Commit dd14ac4

Browse files
committed
链表
1 parent 830ad51 commit dd14ac4

7 files changed

+472
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# 原题链接
2+
- [codetop](https://codetop.cc/home)
23
- [leetcode](https://leetcode-cn.com/problemset/algorithms/)
34
- [热题HOT100](https://leetcode-cn.com/problem-list/2cktkvj/)
45
- [剑指Offer](https://www.nowcoder.com/ta/coding-interviews)

leetcode_Java/DoneTitle.txt

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
11. 盛最多水的容器
77
15. 三数之和
88
17. 电话号码的字母组合
9+
19. 删除链表的倒数第 N 个结点
910
20. 有效的括号
1011
21. 合并两个有序链表
1112
22. 括号生成
@@ -41,6 +42,7 @@
4142
136. 只出现一次的数字
4243
139. 单词拆分
4344
141. 环形链表
45+
142. 环形链表 II
4446
144. 二叉树的前序遍历
4547
145. 二叉树的后序遍历
4648
152. 乘积最大子数组
@@ -49,6 +51,7 @@
4951
169. 多数元素
5052
188. 买卖股票的最佳时机 IV
5153
200. 岛屿数量
54+
203. 移除链表元素
5255
206. 反转链表
5356
216. 组合总和 III
5457
226. 翻转二叉树
@@ -85,6 +88,7 @@
8588
674. 最长连续递增序列
8689
695. 岛屿的最大面积
8790
698. 划分为k个相等的子集
91+
707. 设计链表
8892
712. 两个字符串的最小ASCII删除和
8993
714. 买卖股票的最佳时机含手续费
9094
718. 最长重复子数组

leetcode_Java/Solution0019.java

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// 19. 删除链表的倒数第 N 个结点
2+
3+
4+
/**
5+
* Definition for singly-linked list.
6+
* public class ListNode {
7+
* int val;
8+
* ListNode next;
9+
* ListNode() {}
10+
* ListNode(int val) { this.val = val; }
11+
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
12+
* }
13+
*/
14+
15+
16+
/*
17+
快慢指针:快指针先走n步,然后快慢指针同时走,直到快指针走完链表,此时慢指针所指节点的下一节点是待删除节点,修改慢指针所指节点的下一节点指针指向为下下节点
18+
*/
19+
class Solution {
20+
public ListNode removeNthFromEnd(ListNode head, int n) {
21+
ListNode root = new ListNode(0, head);
22+
ListNode slow = root;
23+
ListNode fast = head;
24+
for (int i = 0; i < n; i++) {
25+
fast = fast.next;
26+
}
27+
while (fast != null) {
28+
fast = fast.next;
29+
slow = slow.next;
30+
}
31+
slow.next = slow.next.next;
32+
return root.next;
33+
}
34+
}
35+
36+
37+
/*
38+
栈:后进先出,全部入栈后弹出n个节点,第n个为待删除节点,此时栈顶节点为前驱节点,修改前驱节点的下一节点指针指向下下节点
39+
*/
40+
class Solution {
41+
public ListNode removeNthFromEnd(ListNode head, int n) {
42+
Stack<ListNode> stack = new Stack<>();
43+
ListNode root = new ListNode(0, head);
44+
ListNode cur = root;
45+
while (cur != null) {
46+
stack.push(cur);
47+
cur = cur.next;
48+
}
49+
while (n > 0) {
50+
stack.pop();
51+
n--;
52+
}
53+
ListNode node = stack.peek();
54+
node.next = node.next.next;
55+
return root.next;
56+
}
57+
}
58+
59+
60+
/*
61+
计数:遍历链表记录链表长度,计算待删除节点正数位置,再从头遍历到待删除节点的前驱节点位置,修改前驱节点的下一节点指针指向下下节点
62+
*/
63+
class Solution {
64+
public ListNode removeNthFromEnd(ListNode head, int n) {
65+
ListNode root = new ListNode(0, head);
66+
ListNode cur = root;
67+
int len = 0;
68+
while (head != null) {
69+
len++;
70+
head = head.next;
71+
}
72+
for (int i = 0; i < len - n; i++) {
73+
cur = cur.next;
74+
}
75+
cur.next = cur.next.next;
76+
return root.next;
77+
}
78+
}
79+
80+
81+
/*
82+
递归:累加计数
83+
1、方法功能:传入节点,返回该节点的倒数位置个数。如果是目标删除位置,则修改链表指针指向下下个节点
84+
2、终止条件:节点为空时,返回位置0
85+
3、递归逻辑:
86+
1)调用递归方法,直接走到链表尾部,逐层累加计数返回
87+
2)接收递归返回值,判断该值是否为目标删除位置,是则说明下一节点是待删除节点,修改链表指针指向下下个节点
88+
*/
89+
class Solution {
90+
public ListNode removeNthFromEnd(ListNode head, int n) {
91+
return rec(head, n) == n ? head.next : head;
92+
}
93+
94+
private int rec(ListNode head, int n) {
95+
if (head == null) {
96+
return 0;
97+
}
98+
int num = rec(head.next, n);
99+
if (num == n) {
100+
head.next = head.next.next;
101+
}
102+
return ++num;
103+
}
104+
}
105+
106+
107+
/*
108+
递归:递减计数
109+
*/
110+
class Solution {
111+
public ListNode removeNthFromEnd(ListNode head, int n) {
112+
return track(head, n) == 0 ? head.next : head;
113+
}
114+
115+
private int track(ListNode head, int num) {
116+
if (head == null) {
117+
return num;
118+
}
119+
num = track(head.next, num);
120+
if (num == 0) {
121+
head.next = head.next.next;
122+
}
123+
return --num;
124+
}
125+
}

leetcode_Java/Solution0141.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public boolean hasCycle(ListNode head) {
5555
快慢指针:
5656
1、慢指针走一步,快指针走两步
5757
2、如果没有环,则快指针会走到空指针
58-
3、如果有环,则慢指针走完一圈,快指针刚好走完两圈,两者同时回到原点
58+
3、如果有环,假设在环中,以快指针为起点,快指针距离慢指针n步,那么当慢指针走n步后的位置为2n,刚好快指针也走2n步,所以会快慢指针会相遇
5959
*/
6060
public class Solution {
6161
public boolean hasCycle(ListNode head) {

leetcode_Java/Solution0142.java

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// 142. 环形链表 II
2+
3+
4+
/**
5+
* Definition for singly-linked list.
6+
* class ListNode {
7+
* int val;
8+
* ListNode next;
9+
* ListNode(int x) {
10+
* val = x;
11+
* next = null;
12+
* }
13+
* }
14+
*/
15+
16+
17+
/*
18+
思路:使用列表存放节点对象,遍历链表,如果节点对象在列表中出现过则该节点为开始入环的第一个节点
19+
注意:列表不能存放节点值,值可能一样,值一样的对象地址不一样,是唯一的
20+
*/
21+
public class Solution {
22+
public ListNode detectCycle(ListNode head) {
23+
List<ListNode> list = new ArrayList<>();
24+
while (head != null) {
25+
if (list.contains(head)) {
26+
return head;
27+
}
28+
list.add(head);
29+
head = head.next;
30+
}
31+
return null;
32+
}
33+
}
34+
35+
36+
/*
37+
使用HashMap存放节点对象
38+
*/
39+
public class Solution {
40+
public ListNode detectCycle(ListNode head) {
41+
HashMap<ListNode, Integer> map = new HashMap();
42+
while (head != null) {
43+
if (map.getOrDefault(head, 0) == 1) {
44+
return head;
45+
}
46+
map.put(head, 1);
47+
head = head.next;
48+
}
49+
return null;
50+
}
51+
}
52+
53+
54+
/*
55+
快慢指针:
56+
1、慢指针走一步,快指针走两步
57+
2、如果没有环,则快指针会走到空指针
58+
3、如果有环,假设在环中,以快指针为起点,快指针距离慢指针n步,那么当慢指针走n步后的位置为2n,刚好快指针也走2n步,所以会快慢指针会相遇
59+
4、入环口位置分析:
60+
1)设非环部分长度为a,环部分长度为b,快慢相遇时,慢指针走了s,快指针走了2s,快指针比慢指针多走了n次b,所以2s=s+nb,即s=nb
61+
2)从链表头部走到入环口需要a+nb步。即走a步到了入环口,每绕一圈b步都会回到入环口
62+
3)由s=nb知慢指针已经走了nb步,走到入环口需要a+nb步,所以慢指针再走a步就可以到入环口了,而从链表头部走到入环口也是a步,所以慢指针与头指针继续走直到相遇的位置就是入环口
63+
64+
1 → 2 → 3 → 4 → 5
65+
↑ ↓
66+
7 ← 6
67+
*/
68+
public class Solution {
69+
public ListNode detectCycle(ListNode head) {
70+
ListNode fast = head;
71+
ListNode slow = head;
72+
while (fast != null && fast.next != null) {
73+
slow = slow.next;
74+
fast = fast.next.next;
75+
if (slow == fast) {
76+
while (head != slow) {
77+
head = head.next;
78+
slow = slow.next;
79+
}
80+
return head;
81+
}
82+
}
83+
return null;
84+
}
85+
}

leetcode_Java/Solution0203.java

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// 203. 移除链表元素
2+
3+
4+
/**
5+
* Definition for singly-linked list.
6+
* public class ListNode {
7+
* int val;
8+
* ListNode next;
9+
* ListNode() {}
10+
* ListNode(int val) { this.val = val; }
11+
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
12+
* }
13+
*/
14+
15+
16+
/*
17+
添加哨兵节点,下一节点有效则指向,无效则跳过
18+
*/
19+
class Solution {
20+
public ListNode removeElements(ListNode head, int val) {
21+
ListNode root = new ListNode(0, head);
22+
ListNode pre = root;
23+
while (pre.next != null) {
24+
if (pre.next.val == val) {
25+
pre.next = pre.next.next;
26+
} else {
27+
pre = pre.next;
28+
}
29+
}
30+
return root.next;
31+
}
32+
}
33+
34+
35+
/*
36+
递归:
37+
1、方法功能:入参是节点和目标值,判断当前节点是否有效,有效则返回当前节点,无效则返回下一节点
38+
2、终止条件:节点为空时返回空
39+
3、递归逻辑:
40+
1)每个节点都需要判断并返回有效节点,因此调用同样的方法
41+
2)当前节点的下一节点指针需要指向有效节点,因此调用递归得到的有效节点赋值给该指针
42+
*/
43+
class Solution {
44+
public ListNode removeElements(ListNode head, int val) {
45+
if (head == null) {
46+
return null;
47+
}
48+
head.next = removeElements(head.next, val);
49+
if (head.val == val) {
50+
return head.next;
51+
}
52+
return head;
53+
}
54+
}

0 commit comments

Comments
 (0)