算法通关村第一关——链表经典问题之双指针专题笔记

我一直觉得双指针是一个非常好用的方法,在链表中可以使用,在数组中依然可以,很灵活。

1. 寻找中间结点

        用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步, fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。

public ListNode middleNode(ListNode head) {
    ListNode slow = head. fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

2. 寻找倒数第K个元素

在这里最重要的思想就是先将fast向后遍历到第k + 1 个结点,slow 仍然指向链表的第一个结点,此时指针fast 与 slow 二者之间刚好间隔 k 个结点。之后两个指针同步向后走,当 fast 走到链表的尾部空节点时,slow 指针刚好指向链表的倒数第K个结点。

这样就很巧妙,主要是思想要理解。

要注意的一点,链表的长度可能小于k,寻找k位置的时候必须判断fast是否为null

public ListNode getKthFromEnd(ListNode head, int k) {
    ListNode fast = head;
    ListNode slow = head;
    while (fast != null && k > 0) {
        fast = fast.next;
        k--;
    }
    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

3. 旋转链表

还是双指针,找到倒数k的位置,也就是两段分割的位置,再将两个链表拼接。

k有可能大于链表长度,所以首先获取一下链表长度len,如果然后k=k % len,如果k == 0,就不用旋转,直接返回头结点。

public ListNode rotateRight(ListNode head, int k) {
    if (head == null || k == 0) {
        return head;
    }
    ListNode temp = head;
    ListNode slow = head;
    ListNode fast = head;
    int len = 0;
    while (head != null) {
        head = head.next;
        len++;
    }
    if (k % len == 0) {
        return temp;
    }
    while ((k % len) > 0) {
        k--;
        fast = fast.next;
    }
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    ListNode res = slow.next;
    slow.next = null;
    fast.next = temp;
    return res;
} 

你可能感兴趣的:(链表,笔记,数据结构)