链表操作练习(Java)

这篇博客介绍了四个核心的链表操作:使用快慢指针判断链表是否存在环,合并两个有序链表,删除链表倒数第n个节点的高效方法,以及如何找到链表的中间节点。这些算法均具有良好的空间和时间复杂度,对于理解和解决链表问题非常有帮助。
摘要由CSDN通过智能技术生成

1. 判断链表中是否有环

		/**
     * 判断链表中是否有环
     * 通过快慢指针法
     * 思路: 快指针一次两步, 慢指针一次一步,
     * 如果链表中没有环, 快指针会到达尾节点, 如果链表中有环, 两指针会相遇
     * 空间复杂度O(1), 时间复杂度O(n)
     * @return
     */
    public static boolean isCircle(Node node) {
        //快慢指针
        Node fast = node;
        Node slow = node;

        //如果链表中有环, 快慢指针终将相遇, 否则将会到链表的末端

        while ((fast = fast.getNext()) != null && fast != slow) {
            fast = fast.getNext();
            if (fast == null) {
                return false;
            } else if (fast == slow) {
                return true;
            } else {
                slow = slow.getNext();
            }
        }
        return fast == slow;
    }

2. 两个有序链表的合并

    /**
     * 两个有序链表的合并(正序)
     * 空间复杂度O(1), 时间复杂度O(m+n)
     */
    public static Node combine(Node node1, Node node2) {
        Node first = new Node();
        Node item = first;
        while (node1 != null && node2 != null) {
            if (node1.getValue() <= node2.getValue()) {
                item.setNext(node1);
                item = node1;
                node1 = node1.getNext();
            } else {
                item.setNext(node2);
                item = node2;
                node2 = node2.getNext();
            }
        }
        return first.getNext();
    }

3. 删除链表倒数第n个节点

    /**
     * 删除链表倒数第n个节点
     * 思路1: 拿一个数组记录所有节点, 然后删除这个节点 (空间复杂度O(n), 时间复杂度O(n))
     * 思路2: 一边遍历一遍反转链表, 再反向遍历, 删除这个节点同时将链表复原 (空间复杂度O(1), 时间复杂度O(n))
     */
    public static Node deleteNode(Node node, int inverseIndex) {
        //第一次遍历, 反转链表
        Node last = null;
        Node item = node;
        Node next = item.getNext();

        while (next != null) {
            item.setNext(last);
            last = item;
            item = next;
            next = next.getNext();
        }

        item.setNext(last);
        //从最后一个节点(item)开始, 准备删除倒数第inverseIndex个节点
        next = last;
        last = null;

        int i = 1;
        while (next != null) {
            //加入删除节点操作
            if (i == inverseIndex) {
                item = next;
                next = next.getNext();
                //因为后移了一步, 需要确定next不为null, 满足反转条件
                if (next == null) {
                    break;
                }
            }
            i++;

            item.setNext(last);
            last = item;
            item = next;
            next = next.getNext();
        }

        item.setNext(last);
        return item;
    }

4. 求链表中间节点

    /**
     * 求链表中间接节点
     *
     * @return
     */
    public static Node middleNode(Node node) {
        Node fast = node;
        Node slow = node;

        while ((fast = fast.getNext()) != null && fast.getNext() != null) {
            fast = fast.getNext();
            slow = slow.getNext();
        }

        return slow;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code tea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值