链表的定义
1 | static class ListNode { |
1.翻转链表
https://leetcode-cn.com/problems/reverse-linked-list/
递归:
- 在遍历链表时,将当前节点cur的next指向前一个元素,
- 由于节点没有引用上一个节点,故初始时设置前一个节点pre = null,
- 在更改引用之前,还需要另一个指针来存储下一个节点next = cur.next。
1 | // 执行用时 :1 ms, 在所有 Java 提交中击败了85.90%的用户 |
迭代:假设链表为 n1–>n2–>n3—n>4–>null,若某部分已经被翻转了 n1–>n2–>n3<--n4
,我们希望3指向2,所以有n3.next.next = n2,要注意n1的下一个必须指向null,故还有个head.next = null操作。
1 | public static ListNode reverseList(ListNode head) { |
2.翻转链表II
https://leetcode-cn.com/problems/reverse-linked-list-ii/
假设以 head – 1–2–3–4–中的1~4进行反转
- 先让头指针的next指向2,
- 再让1的next指向3,
- 最后将2的next指向1,
完成第一次交换,顺序变成header–2–1–3–4,
- 然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转。
同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 > class Solution {
> public ListNode reverseBetween(ListNode head, int m, int n) {
> ListNode res = new ListNode(0);
> res.next = head;
> ListNode pre = res;
> for(int i = 1; i < m; i++){
> pre = pre.next;
> }
> head = pre.next;
> for(int i = m; i < n; i++){
> ListNode nextnode = head.next;
> head.next = nextnode.next;
> nextnode.next = pre.next;
> pre.next = nextnode;
> }
> return res.next;
> }
> }
>
3.环形链表
https://leetcode-cn.com/problems/linked-list-cycle/
方法1:HashSet,如果当前结点存在于哈希表中,说明有环,否则遍历完全,返回false。
1 | public static boolean hasCycle(ListNode head) { |
方法2:快慢指针,快指针先于慢指针一步,如果有环,总有一个时刻快指针会追上慢指针。
1 | //执行用时 :1 ms, 在所有 Java 提交中击败了92.84%的用户 |
4.环形链表II
https://leetcode-cn.com/problems/linked-list-cycle-ii/
快慢指针:当fast和slow在环中相遇时,设头节点到入环结点的长度为x,入环结点到相遇点长度为y,相遇点到入环结点长度为z,则有(x+y)*2 = x+y+z+y,即x = z,把快指针设为头节点,慢指针还在相遇点,两个指针相遇之时就是入环点所在之处。
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//执行用时 :1 ms, 在所有 Java 提交中击败了99.71%的用户
//内存消耗 :36.3 MB, 在所有 Java 提交中击败了5.03%的用户
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null)
return null;
ListNode fast = head;
ListNode slow = head;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
//环内相遇
if(fast == slow){
//快指针重头走
fast = head;
//快慢指针同时走,相等时即入环结点处
while(fast !=slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
//走到尾巴了,说明没有环
return null;
}
5.两数相加
https://leetcode-cn.com/problems/add-two-numbers/
1 | public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { |
6.两数相加II
https://leetcode-cn.com/problems/add-two-numbers-ii/submissions/
思路1:使用翻转,进行计算,结果再次翻转即可
1 | public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { |
思路2: 不使用翻转,使用栈进行存储
1 |
|
7.删除排序链表中的重复元素
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/
1 | public ListNode deleteDuplicates(ListNode head) { |
8.删除排序链表中的重复元素II
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/
1 | public static ListNode deleteDuplicates(ListNode head) { |
9.相交链表
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
关键:消除两个链表的长度差
- 指针 pA 指向 A 链表,指针 pB 指向 B 链表,依次往后遍历
- 如果 pA 到了末尾,则 pA = headB 继续遍历
- 如果 pB 到了末尾,则 pB = headA 继续遍历
比较长的链表指针指向较短链表head时,长度差就消除了
如此,只需要将最短链表遍历两次即可找到位置
1
2
3
4
5
6
7
8
9public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}