[剑指offer] 链表篇
JZ6 从尾到头打印链表
1 /* 从尾到头递归 */
2 public class JZ6_1
3 {
4 private static ArrayList<Integer> res = new ArrayList<>();
5
6 public static ArrayList<Integer> printListFromTailToHead(ListNode listNode)
7 {
8 if (listNode != null)
9 {
10 printListFromTailToHead(listNode.next);
11 res.add(listNode.val);
12 }
13 return res;
14 }
15 }
16
17 /* ArrayList.add(int index, E element) */
18 public class JZ6_2
19 {
20 public static ArrayList<Integer> printListFromTailToHead(ListNode listNode)
21 {
22 ArrayList<Integer> res = new ArrayList<>();
23 while (listNode != null)
24 {
25 res.add(0, listNode.val);
26 listNode = listNode.next;
27 }
28 return res;
29 }
30 }
31
32 /* 栈 */
33 public class JZ6_3
34 {
35 public static ArrayList<Integer> printListFromTailToHead(ListNode listNode)
36 {
37 ArrayList<Integer> res = new ArrayList<>();
38 Stack<Integer> temp = new Stack<>();
39 while (listNode != null)
40 {
41 temp.add(listNode.val);
42 listNode = listNode.next;
43 }
44 while (!temp.isEmpty())
45 {
46 res.add(temp.pop());
47 }
48 return res;
49 }
50 }
51
52 /* 原地反转链表 */
53 public class JZ6_4
54 {
55 public static ArrayList<Integer> printListFromTailToHead(ListNode listNode)
56 {
57 ListNode pre = null, cur = listNode, temp = null;
58 ArrayList<Integer> res = new ArrayList<>();
59 while (cur != null)
60 {
61 temp = cur.next;
62 cur.next = pre;
63 pre = cur;
64 cur = temp;
65 }
66 while (pre != null)
67 {
68 res.add(pre.val);
69 pre = pre.next;
70 }
71 return res;
72 }
73 }
74
75 /* 递归反转链表 */
76 public class JZ6_5
77 {
78 public static ArrayList<Integer> printListFromTailToHead(ListNode listNode)
79 {
80 ArrayList<Integer> res = new ArrayList<>();
81
82 ListNode reverseList = reverse(listNode);
83 while (reverseList != null)
84 {
85 res.add(reverseList.val);
86 reverseList = reverseList.next;
87 }
88 return res;
89 }
90
91 public static ListNode reverse(ListNode node)
92 {
93 if (node == null || node.next == null) return node;
94 ListNode fir = node, sec = node.next;
95 fir.next = null;
96 ListNode temp = sec;
97 ListNode reverse = reverse(sec);
98 temp.next = fir;
99 return reverse;
100 }
101 }
JZ24 反转链表
1 /* 从尾到头递归 */
2 public class JZ24_1
3 {
4 public static ListNode res, tail;
5
6 public static ListNode ReverseList(ListNode listNode)
7 {
8 if (listNode != null)
9 {
10 ReverseList(listNode.next);
11 if (res == null)
12 res = tail = listNode;
13 else
14 {
15 tail.next = listNode;
16 tail = tail.next;
17 tail.next = null;
18 }
19 }
20 return res;
21 }
22 }
23
24 /* 栈 */
25 public class JZ24_2
26 {
27 public static ListNode ReverseList(ListNode listNode)
28 {
29 ListNode head = new ListNode(-1), tail = head;
30 Stack<Integer> temp = new Stack<>();
31 while (listNode != null)
32 {
33 temp.add(listNode.val);
34 listNode = listNode.next;
35 }
36 while (!temp.isEmpty())
37 {
38 tail.next = new ListNode(temp.pop());
39 tail = tail.next;
40 }
41 return head.next;
42 }
43 }
44
45 /* 原地反转链表 */
46 public class JZ24_3
47 {
48 public static ListNode ReverseList(ListNode listNode)
49 {
50 ListNode pre = null, cur = listNode, temp = null;
51 while (cur != null)
52 {
53 temp = cur.next;
54 cur.next = pre;
55 pre = cur;
56 cur = temp;
57 }
58 return pre;
59 }
60 }
61
62 /* 递归反转链表 */
63 public class JZ24_4
64 {
65 public static ListNode ReverseList(ListNode listNode)
66 {
67 if (listNode == null || listNode.next == null) return listNode;
68 ListNode fir = listNode, sec = listNode.next;
69 fir.next = null;
70 ListNode temp = sec;
71 ListNode reverse = ReverseList(sec);
72 temp.next = fir;
73 return reverse;
74 }
75 }
JZ25 合并两个排序的链表
1 /* 归并 */
2 public class JZ25_1
3 {
4 public static ListNode Merge(ListNode pHead1, ListNode pHead2)
5 {
6 ListNode res = new ListNode(-1), tail = res;
7 while (pHead1 != null && pHead2 != null)
8 {
9 if (pHead1.val <= pHead2.val)
10 {
11 tail.next = pHead1;
12 pHead1 = pHead1.next;
13 }
14 else
15 {
16 tail.next = pHead2;
17 pHead2 = pHead2.next;
18 }
19 tail = tail.next;
20 tail.next = null;
21 }
22 tail.next = pHead1 == null ? pHead2 : pHead1;
23 return res.next;
24 }
25 }
26
27 /* ⭐递归⭐ */
28 public class JZ25_2
29 {
30 public static ListNode Merge(ListNode pHead1, ListNode pHead2)
31 {
32 if (pHead1 == null) return pHead2;
33 if (pHead2 == null) return pHead1;
34 if (pHead1.val <= pHead2.val)
35 {
36 pHead1.next = Merge(pHead1.next, pHead2);
37 return pHead1;
38 }
39 else
40 {
41 pHead2.next = Merge(pHead1, pHead2.next);
42 return pHead2;
43 }
44 }
45 }
JZ52 两个链表的第一个公共结点
1 /* 让长链表先走两个链表的长度差,然后再一起走 */
2 public class JZ52_1
3 {
4 public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2)
5 {
6 int cnt1 = 0, cnt2 = 0;
7 ListNode p1 = pHead1, p2 = pHead2;
8 while (p1 != null)
9 {
10 cnt1++;
11 p1 = p1.next;
12 }
13 while (p2 != null)
14 {
15 cnt2++;
16 p2 = p2.next;
17 }
18 if (cnt1 > cnt2)
19 {
20 for (int i = 0; i < cnt1 - cnt2; i++)
21 pHead1 = pHead1.next;
22 }
23 else
24 {
25 for (int i = 0; i < cnt2 - cnt1; i++)
26 pHead2 = pHead2.next;
27 }
28 while (pHead1 != pHead2)
29 {
30 pHead1 = pHead1.next;
31 pHead2 = pHead2.next;
32 }
33 return pHead1;
34 }
35 }
36
37 /* ⭐长链表遍历完遍历短链表,短链表遍历完遍历长链表⭐ */
38 public class JZ52_2
39 {
40 public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2)
41 {
42 ListNode p1 = pHead1, p2 = pHead2;
43 while (p1 != p2)
44 {
45 p1 = p1 == null ? pHead2 : p1.next;
46 p2 = p2 == null ? pHead1 : p2.next;
47 }
48 return p1;
49 }
50 }
JZ23 链表中环的入口结点⭐
1 /*
2 * 快慢双指针,假设链表环的长度为 m
3 * 慢指针(每次走一步), 从头节点走到入口节点的距离为 x, 从入口节点走到与快指针相遇的位置为 y (y<m), 即一共走了 x+y 的距离
4 * 快指针(每次走两步), 因为速度是慢指针的两倍, 所以一共走了 2(x+y) 的距离
5 * 即 y%m = (x+2y)%m
6 * 得到 x + y = 整数倍的m
7 * 所以 x = 整数倍的m - y
8 * 所以在快慢指针相遇后, 一个指针从头节点出发, 一个指针从相遇位置出发, 每次各自走一步, 当他们相遇时, 即为入口节点
9 * */
10 public class JZ23_1
11 {
12 public static ListNode EntryNodeOfLoop(ListNode pHead)
13 {
14 ListNode slow = pHead, fast = pHead;
15 while (fast.next != null && fast.next.next != null)
16 {
17 slow = slow.next;
18 fast = fast.next.next;
19 if (slow == fast)
20 {
21 while (pHead != fast)
22 {
23 pHead = pHead.next;
24 fast = fast.next;
25 }
26 return pHead;
27 }
28 }
29 return null;
30 }
31 }
JZ22 链表中倒数最后k个结点
1 /* 双指针 */
2 public class JZ22_1
3 {
4 public static ListNode FindKthToTail(ListNode pHead, int k)
5 {
6 ListNode pre = pHead, last = pHead;
7 for (int i = 0; i < k; i++)
8 {
9 if (last == null) return null;
10 last = last.next;
11 }
12 while (last != null)
13 {
14 last = last.next;
15 pre = pre.next;
16 }
17 return pre;
18 }
19 }
JZ35 复杂链表的复制⭐
1 /* 分成三步 */
2 public class JZ35_1
3 {
4 public static RandomListNode Clone(RandomListNode pHead)
5 {
6 RandomListNode head = pHead, res = null, tail = null;
7 while (head != null)
8 {
9 RandomListNode temp = new RandomListNode(-head.label);
10 temp.next = head.next;
11 head.next = temp;
12 head = head.next.next;
13 }
14
15 head = pHead;
16 while (head != null)
17 {
18 if (head.random == null)
19 head.next.random = null;
20 else
21 head.next.random = head.random.next;
22 head = head.next.next;
23 }
24 head = pHead;
25 while (head != null)
26 {
27 if (res == null)
28 {
29 res = tail = head.next;
30 }
31 else
32 {
33 tail.next = head.next;
34 tail = tail.next;
35 }
36 head.next = head.next.next;
37 head = head.next;
38 }
39 return res;
40 }
41 }
42
43 /* HashMap */
44 public class JZ35_2
45 {
46 public static RandomListNode Clone(RandomListNode pHead)
47 {
48 HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
49 RandomListNode p = pHead, res = null, tail = null;
50 while (p != null)
51 {
52 RandomListNode temp = new RandomListNode(p.label);
53 if (res == null)
54 res = tail = temp;
55 else
56 {
57 tail.next = temp;
58 tail = tail.next;
59 }
60 map.put(p, temp);
61 p = p.next;
62 }
63 p = pHead;
64 tail = res;
65 while (p != null)
66 {
67 if (p.random == null)
68 tail.random = null;
69 else
70 tail.random = map.get(p.random);
71 p = p.next;
72 tail = tail.next;
73 }
74 return res;
75 }
76 }
JZ76 删除链表中重复的结点
1 /* 一边遍历一边构造 */
2 public class JZ76_1
3 {
4 public static ListNode deleteDuplication(ListNode pHead)
5 {
6 if (pHead == null || pHead.next == null) return pHead;
7 ListNode res = new ListNode(-1), tail = res;
8 while (pHead != null)
9 {
10 if (pHead.next == null || pHead.val != pHead.next.val)
11 {
12 tail.next = pHead;
13 tail = pHead;
14 }
15 while (pHead.next != null && pHead.val == pHead.next.val)
16 pHead = pHead.next;
17 pHead = pHead.next;
18 }
19 tail.next = null;
20 return res.next;
21 }
22 }
23
24 /* ⭐递归⭐ */
25 public class JZ76_2
26 {
27 public static ListNode deleteDuplication(ListNode pHead)
28 {
29 if (pHead == null || pHead.next == null) return pHead;
30 if (pHead.val != pHead.next.val)
31 {
32 pHead.next = deleteDuplication(pHead.next);
33 return pHead;
34 }
35 else
36 {
37 ListNode temp = pHead;
38 while (temp != null && temp.val == pHead.val) temp = temp.next;
39 return deleteDuplication(temp);
40 }
41 }
42 }
JZ18 删除链表的节点
1 /* 遍历 */
2 public class JZ18_1
3 {
4 public static ListNode deleteNode(ListNode head, int val)
5 {
6 if (head.val == val)
7 return head.next;
8 ListNode pre = head, last = head.next;
9 while (last != null)
10 {
11 if (last.val == val)
12 {
13 pre.next = last.next;
14 }
15 last = last.next;
16 pre = pre.next;
17 }
18 return head;
19 }
20 }
21
22 /* 递归 */
23 public class JZ18_2
24 {
25 public static ListNode deleteNode(ListNode head, int val)
26 {
27 if (head.val == val) return head.next;
28 head.next = deleteNode(head.next, val);
29 return head;
30 }
31 }