IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 第二章 链表问题(两个单链表相交的一系列问题) -> 正文阅读

[数据结构与算法]第二章 链表问题(两个单链表相交的一系列问题)

【题目】

? ? ? ?单链表可能有环,可能无环头节点 head1 和 head2, 这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交, 请返回相交的第一个节点; 如果不相交, 返回 null 即可。
?如果链表1的长度为N,链表2的长度为M,时间复杂度请达到O(N + M),额外的空间复杂度请达到O(1)。

【解答】

?????????三个子问题,具体如下。
? ????????问题一:如何判断一个链表是否有环,如果有,返回第一个进入环的节点,没有则返回null。
? ????????问题二:如何判断两个无环链表是否相交,相交则返回第一个相交节点,不相交则返回null。
? ????????问题三:如何判断两个有环链表是否相交,相交则返回第一个相交节点,不相交返回null。
? ????????注意:一个链表有环,一个无环,二者不可相交,直接返回null。

????????

package base;

public class P69_NodeCross {

    /**
     * 获取入环节点
     * @param node1 节点1
     * @param node2 节点2
     * @return
     */
    public static Node getCrossNode(Node node1, Node node2) {
        if (null == node1 || null == node2) {
            return null;
        }
        // 查看是否有环
        Node loop1 = isCircle(node1);
        Node loop2 = isCircle(node2);
        // 1、无环相交
        if (null == loop1 && null == loop2) {
            return noCircleCross(node1, node2);
        }
        // 2、有环相交
        if (loop1 != null && loop2 != null) {
            return nodeCross(node1, loop1, node2, loop2);
        }
        return null;
    }


    // 设置一个快慢指针,如果链表有环,那么快指针和慢指针一定会在环中的某个位置相遇,当快指针和慢指针相遇时,快指针重新回到head位置,
    // 改为每次移动一步,慢指针依然一次移动一步;快慢指针再次相遇的位置,就是入环节点
    public static Node isCircle(Node node) {
        if (node.next == null || node.next.next == null) {
            return null;
        }
        Node slow = node.next;
        Node fast = node.next.next;
        while (slow != fast) {
            if (fast.next == null || fast.next.next == null) {
                return null;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        fast = node;
        while (slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }

    /**
     * 无环相交
     * 如果两个无环节点相交,那么从相交节点开始,一直到两个链表终止的这一段,是连个链表共享的
     * @param head1
     * @param head2
     * @return
     */
    public static Node noCircleCross(Node head1, Node head2) {
        int n = 0;
        Node node1 = head1;
        while (node1 != null) {
            node1 = node1.next;
            n++;
        }
        Node node2 = head2;
        while (node2 != null) {
            node2 = node2.next;
            n--;
        }
        // node1 为长度较长节点
        node1 = n > 0 ? head1 : head2;
        node2 = node1 == head1 ? head2 : head1;
        n = Math.abs(n);
        // node1 先走n步,然后两个链表一起走,两个链表第一次走到一起的节点就是第一个相交节点
        while (n > 0) {
            n--;
            node1 = node1.next;
        }
        while (node1 != null && node2 != null) {
            if (node1 == node2) {
                return node1;
            }
            node1 = node1.next;
            node2 = node2.next;
        }
        return null;
    }

    /**
     * 有环相交
     * @param head1 节点1
     * @param loop1 入环节点1
     * @param head2 节点2
     * @param loop2 入环节点2
     * @return
     */
    public static Node nodeCross(Node head1, Node loop1, Node head2, Node loop2) {
        // 如果入环节点相等
        if (loop1 == loop2) {
            int n = 0;
            Node node1 = head1;
            while (node1 != loop1) {
                node1 = node1.next;
                n++;
            }
            Node node2 = head2;
            while (node2 != loop2) {
                node2 = node2.next;
                n--;
            }
            node1 = n > 0 ? head1 : head2;
            node2 = node1 == head1 ? head2 : head1;
            n = Math.abs(n);
            while (n > 0) {
                n--;
                node1 = node1.next;
            }
            while (node1 != node2) {
                node1 = node1.next;
                node2 = node2.next;
            }
            return node1;
        } else {
            Node temp1 = loop1.next;
            while (temp1 != loop1) {
                if (temp1 == loop2) {
                    return loop2;
                }
                temp1 = temp1.next;
            }
        }
        return null;
    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 14:50:26  更:2021-07-29 14:50:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 11:08:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码