链表总结

66 阅读1分钟

链表

mp.weixin.qq.com/s/_QVP3IkRZ…

mp.weixin.qq.com/s/vK0JjSTHf…

1.链表结构定义

public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int x) {
        val = x;
    }
​
    @Override
    public String toString() {
        if (this.next == null) {
            return this.val+"";
        }
        return this.val + "->" + this.next;
    }
}

链表删除定值节点

直接操作next指向下一个,为了防止被删除节点是第一个,新增虚拟头节点可以使代码统一

image.png

    public ListNode deleteNode(ListNode head, int val) {
        ListNode result = new ListNode(-1);
        ListNode handle = new ListNode(-1);
        result.next = handle;
        handle.next = head;
        while(handle!=null) {
            ListNode next = handle.next;
            if (next!=null && next.val == val) {
                handle.next = next.next;
            }
            handle = handle.next;
        }
        return result.next.next;
    }

删除倒数第几个节点

快慢指针,一次遍历,找到目标节点,删除

    public ListNode removeNthFromEnd(ListNode head, int n) {
        // write code here
        // input check ?
        ListNode handle = new ListNode(-1);
        handle.next = head;
        ListNode fast = handle;
        ListNode slow = handle;
        for (int i=0; i < n;i++){
            fast = fast.next;
        }
        // 找到 倒数N 
        while (fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        // 跳过倒数N
        slow.next = slow.next.next;
        return handle.next;
    }

反转链表

双指针法,持续维护pre 和 cur两个节点

image.png

    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode current = head;
        while (current !=null)
        {
            ListNode next = current.next;
            current.next = pre;
            pre = current;
            current = next;
        }
        return pre;
    }

使用递归法,第一次维护一个空的pre

    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        return revert(pre, head);
    }
​
    private ListNode revert(ListNode pre, ListNode head) {
        if (head == null) {
            return pre;
        }
        ListNode next = head.next;
        head.next = pre;
        return revert(head,next);
    }

链表找环

是否有环:快慢指针可以相遇,环的入口:在相遇的点,新节点从头开始走,新节点和快指针相遇的地方为环的入口

从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

image.png

            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }

\