单链表算法

文章目录

单链表反转

public class Test {
    // 单链表遍历
    public static void ergodic(Node curr){
        while(curr != null){
            System.out.print(curr.item);
            curr = curr.next;
        }
        System.out.println();
    }
    // 单链表反转
    public static Node reverse(Node list) {
        // 将 list 标为 当前节点,并 初始化 前节点 pre 为 null
        Node curr = list, pre = null;
        // 当前节点为 null 时,则退出循环
        while(curr != null){
            // 将 当前节点 的 后节点 保存到 next
            Node next = curr.next;
            // 将 前节点pre 标记为 当前节点 的 后节点
            curr.next = pre;
            // 将 当前节点 标记为 前节点
            pre = curr;
            // 将 next 标记为 当前节点
            curr = next;
        }
        return pre;
    }
    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(1,null);
        Node<Integer> node2 = new Node<>(2,node1);
        Node<Integer> node3 = new Node<>(3,node2);
        Node<Integer> node4 = new Node<>(4,node3);
        ergodic(node4);
        Node reverse = reverse(node4);
        ergodic(reverse);
    }
}

class Node<E> {
    E item;       // 当前元素的值
    Node<E> next; // 指向下一个元素

    Node(E element, Node<E> next) {
        this.item = element;
        this.next = next;
    }
}

链表中环的检测

快慢指针:

  • 无终点长跑中,如果直线跑,快慢两个人的距离会越来越大,不可能相遇,
  • 如果绕环跑,则快慢两个人必然相遇
public class Test {
    // 检测环
    public static boolean checkCircle(Node list) {
        // 链表为 null 直接返回 false
        if(list == null) return false;
        // 初始化快慢指针
        Node fast = list.next, slow = list;
        // 如果无环,则 快指针 先到 尾结点
        while(fast != null && fast.next != null){
            // 快指针 一步 跑 两格
            fast = fast.next.next;
            // 慢指针 一步 跑 一格
            slow = slow.next;
            // 如果 快慢指针 相遇,则说明有环,如果无环,则 快指针 先到 尾结点
            if(fast == slow) return true;
        }
        // 快指针 已经 到了 尾结点
        return false;
    }
    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(1,null);
        Node<Integer> node2 = new Node<>(2,node1);
        Node<Integer> node3 = new Node<>(3,node2);
        Node<Integer> node4 = new Node<>(4,node3);
        node1.next = node4;
        System.out.println(checkCircle(node4));
    }
}

class Node<E> {
    E item;       // 当前元素的值
    Node<E> next; // 指向下一个元素

    Node(E element, Node<E> next) {
        this.item = element;
        this.next = next;
    }
}

两个有序的链表合并

public class Test {
    // 单链表遍历
    public static void ergodic(Node curr){
        while(curr != null){
            System.out.print(curr.item);
            curr = curr.next;
        }
        System.out.println();
    }
    // 有序链表合并 Leetcode 21
    public static Node mergeTwoLists(Node<Integer> l1, Node<Integer> l2) {
        // 利用哨兵结点简化实现难度
        Node<Integer> soilder = new Node<>(0,null);
        // 初始化当前节点
        Node<Integer> curr = soilder;
        // 只要有一个链表遍历结束,另一个链表的剩余节点都将大于新链表
        while(l1 != null && l2 != null){
            // 将较小值 作为 当前节点 的 后节点
            if(l1.item < l2.item){
                curr.next = l1;
                // 更新 l1 节点
                l1 = l1.next;
            }else{
                curr.next = l2;
                l2 = l2.next;
            }
            // 更新当前节点
            curr = curr.next;
        }
        // 将 未遍历完 的 链表 直接 放到 新链表 尾部
        if(l1 != null) curr.next = l1;
        if(l2 != null) curr.next = l2;
        // 返回 不含 哨兵节点 的 链表
        return soilder.next;
    }
    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(7,null);
        Node<Integer> node2 = new Node<>(5,node1);
        Node<Integer> node3 = new Node<>(3,node2);
        Node<Integer> node4 = new Node<>(1,node3);
        Node<Integer> node5 = new Node<>(8,null);
        Node<Integer> node6 = new Node<>(6,node5);
        Node<Integer> node7 = new Node<>(4,node6);
        Node<Integer> node8 = new Node<>(2,node7);
        ergodic(mergeTwoLists(node4,node8));
    }
}

class Node<E> {
    E item;       // 当前元素的值
    Node<E> next; // 指向下一个元素

    Node(E element, Node<E> next) {
        this.item = element;
        this.next = next;
    }
}

删除链表倒数第 n 个结点

public class Test {
    // 删除倒数第K个结点
    public static Node deleteLastKth(Node list, int k) {
        Node fast = list;
        int i = 1;
        while (fast != null && i < k) {
            fast = fast.next;
            ++i;
        }

        if (fast == null) return list;

        Node slow = list, prev = null;

        while (fast.next != null) {
            fast = fast.next;
            prev = slow;
            slow = slow.next;
        }

        if (prev == null) {
            list = list.next;
        } else {
            prev.next = prev.next.next;
        }
        return list;
    }
    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(1,null);
        Node<Integer> node2 = new Node<>(2,node1);
        Node<Integer> node3 = new Node<>(3,node2);
        Node<Integer> node4 = new Node<>(4,node3);
        Node<Integer> node5 = new Node<>(5,node4);
        Node<Integer> node6 = new Node<>(6,node5);
        System.out.println(deleteLastKth(node6,5).next.item);
    }
}

class Node<E> {
    E item;       // 当前元素的值
    Node<E> next; // 指向下一个元素

    Node(E element, Node<E> next) {
        this.item = element;
        this.next = next;
    }
}

求链表的中间结点

public class Test {
    // 求中间结点
    public static Node findMiddleNode(Node list) {
        if(list == null) return null;
        Node fast =list, slow = list;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(1,null);
        Node<Integer> node2 = new Node<>(2,node1);
        Node<Integer> node3 = new Node<>(3,node2);
        Node<Integer> node4 = new Node<>(4,node3);
        Node<Integer> node5 = new Node<>(5,node4);
        Node<Integer> node6 = new Node<>(6,node5);
        System.out.println(findMiddleNode(node6).item);
    }
}

class Node<E> {
    E item;       // 当前元素的值
    Node<E> next; // 指向下一个元素

    Node(E element, Node<E> next) {
        this.item = element;
        this.next = next;
    }
}
上一篇:算法---LeetCode 235. 二叉搜索树的最近公共祖先(同剑指offer 68-1)


下一篇:【python】Leetcode每日一题-二叉搜索树节点最小距离