链表(2)

691 阅读2分钟

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的距离相同,直接再走一遍求交点即可。

相交链表II.png

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;
  }
}