Java 实现两个链表的第一个公共结点

本文介绍两种寻找两个链表首个公共节点的方法:一是利用栈结构逆向比较;二是通过调整链表起始位置实现同步遍历比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输入两个链表,找出它们的第一个公共结点。

代码

解法一

利用栈的后入先出特性,来从尾部找第一个公共节点

    static class ListNode {
        int val;
        ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }

    /**
     * 两个链表的第一个公共结点
     *        1 -> 2  -> 3 -> 4
     *                   +
     * 11 -> 18 -> 19 -> 3 -> 4
     * 这种链表可以认为是Y型链表,从前往后找比较困难,但是链表只保存next节点,也不好从后往前找
     * 所以借助栈结构,遍历链表,依次入栈,结合栈的后进先出特性,来从后往前比较两个链表,直至找到第一个公共节点
     * @param root1
     * @param root2
     * @return
     */
    public static int findShareNode(ListNode root1, ListNode root2) {
        if (root1 == null || root2 == null) {
            throw new IllegalArgumentException("root1 or root 2 is null");
        }
        Stack<ListNode> stack1 = new Stack<>();
        Stack<ListNode> stack2 = new Stack<>();
        while (root1 != null) {
            stack1.push(root1);
            root1 = root1.next;
        }
        int result = -1;
        while (root2 != null) {
            stack2.push(root2);
            root2 = root2.next;
        }
        while (!stack1.isEmpty() && !stack2.isEmpty()) {
            root1 = stack1.pop();
            root2 = stack2.pop();
            if (root1.val == root2.val) {
                result = root1.val;
            } else {
                break;
            }
        }
        return result;
    }

解法二

计算两个链表的长度,使较长的链表先移动链表长度差的步长,然后再依次比较两个链表相同位置上的节点。

    /**
     * 两个链表的第一个公共结点
     *        1 -> 2  -> 3 -> 4
     *                   +
     * 11 -> 18 -> 19 -> 3 -> 4
     * 这种链表可以认为是Y型链表,从上面可以看出,11这个节点没有可比性,因为两个链表不等长,多出的部分不需要进行比较
     * 所以先将较长的链表走一定的步数,当其剩余的长度和另一个链表长度相等时,同时遍历,进行比较,找出第一个公共节点
     * @param root1
     * @param root2
     * @return
     */
    public static int findShareNode2(ListNode root1, ListNode root2) {
        if (root1 == null || root2 == null) {
            throw new IllegalArgumentException("root1 or root 2 is null");
        }
        int root1Length = 0;
        int root2Length = 0;
        ListNode tempRoot1 = root1;
        ListNode tempRoot2 = root2;
        // 计算root1的长度
        while (tempRoot1 != null) {
            tempRoot1 = tempRoot1.next;
            root1Length++;
        }
        // 计算root2的长度
        while (tempRoot2 != null) {
            tempRoot2 = tempRoot2.next;
            root2Length++;
        }
        // 计算两个链表的长度差
        int i = Math.abs(root1Length - root2Length);
        // 判断先让哪个链表走k步,k=length1-length2
        // 从而使得两个链表以相同的长度来进行查找第一个公共节点
        if (root1Length > root2Length) {
            while (i > 0 && root1 != null) {
                root1 = root1.next;
                i--;
            }
        } else {
            while (i > 0 && root2 != null) {
                root2 = root2.next;
                i--;
            }
        }
        // 此时两个链表长度一致,依次对比相同位置上的节点
        // 如果一致,说明是第一个公共节点
        while (root1 != null && root2 != null) {
            if (root1.val == root2.val) {
                return root1.val;
            }
            root1 = root1.next;
            root2 = root2.next;
        }
        return -1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值