Day 04 链表花式翻转、相交链表
1、K个一组翻转链表
- 解题思路: Node[0]、Node[k-1]区间翻转,然后继续翻转下个区间
难点:每K个区间翻转要相互连接起来
- 循环解法
class Solution { public ListNode reverseKGroup(ListNode head, int k) { ListNode fast = head; for (int i = 0; i < k ; i++) { //如果不满足k个直接返回head,不进行翻转 if (fast == null){ return head; } fast = fast.next; } ListNode ans = reverse(head,fast); //此时head节点为区间的尾部,应该跟下一个连接 head.next = reverseKGroup(fast,k); return ans; } /** * 区间翻转 */ private ListNode reverse(ListNode start,ListNode end){ ListNode pre = null; ListNode next = start; while (start != end){ next = start.next; start.next = pre; pre = start; start = next; } return pre; } }- 递归解法
class Soluion{ public ListNode reverseKGroup(ListNode head, int k) { ListNode index = head; for (int i = 0; i < k; i++) { if (index == null){ return head; } index = index.next; } ListNode node = reverseK(head, k); head.next = reverseKGroup(index,k); return node; } private ListNode reverseK(ListNode head,int k){ if (head == null || head.next == null || k == 1){ return head; } ListNode res = reverseK(head.next,k - 1); ListNode temp = head.next; temp.next = head; //利用每次一递归的head.next来保存第k+1的节点 head.next = temp.next; return res; } }
2、相交链表
- 思路:
- 利用哈希表记录其中一个链表,在去另一个链表中一次比对哈希表中是否存在该Node
- 两个链表每次走相同的步长,当任意一个节点走完,就去走另外一个节点。如果有交点,那最终两个Index相同,直接返回。如果没有交点,在走完相同长度(n+m)之后,两个Index相交于null。
public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode indexA = headA; ListNode indexB = headB; while (indexA != indexB){ if (indexA != null){ indexA = indexA.next; }else { indexA = headB; } if (indexB != null){ indexB = indexB.next; }else { indexB = headA; } } return indexA; } }
3、环形链表 II
- 思路:
-
假设有环。设开始点s到环的入口m的距离为x。
-
取快慢指针low、fast。fast步长为low的两倍,若遍历结束fast==low则证明有环(链表判断是否有环的基础解法)
-
若此时相交点为g。记low走的步长为L,则fast的步长为2L。m-g为y。g-m为z
-
则 x + y = L , y * 2 + z + x = 2L。解出 z = x
-
说明,此时low从head点到m的距离和fast从g到m的距离相同,直接再走一遍求交点即可。
-
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) return head;
ListNode fast = head;
ListNode low = head;
while (fast != null && fast.next != null){
fast = fast.next.next;
low = low.next;
//有环
if (fast == low){
break;
}
}
//跳出循环,有可能是因为无环
if (fast == null || fast.next == null) return null;
low = head;
while (fast != low){
fast = fast.next;
low = low.next;
}
return fast;
}
}