算法通关村第一关-链表白银挑战笔记|公共子节点

两个链表公共子节点问题

题目:

这是一道非常经典的链表题目,也属于常考的问题。 已知:两个链表,找到相交点 注意:

如果两个链表没有交点,返回 null. 在返回结果后,两个链表仍须保持原有的结构。 可假定整个链表结构中没有循环。 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

提供四种解决方法的思路:

  • 哈希表或集合实现 ⭐
  • 使用栈确定实现 ⭐⭐
  • 拼接字符串实现 ⭐⭐⭐
  • 和差双指针实现 ⭐⭐⭐⭐⭐

哈希表或集合解决

先将一个链表元素全部存到Map里,然后一边遍历第二个链表,一边检测Hash中是否存在当前结点,如果有交点,那么一定能检测出来。 对于本题,如果使用集合更适合,而且代码也更简洁。思路和上面的一样,直接看代码:

java 复制代码
/**
 * 方法1:通过Hash辅助查找
 *
 * @param pHead1
 * @param pHead2
 * @return
 */
public static ListNode findFirstCommonNodeByMap(ListNode pHead1, ListNode pHead2) {
    // 检测参数
    if (pHead1 == null || pHead2 == null){
        return null;
    }
    // 保存头节点
    ListNode cur1 = pHead1;
    ListNode cur2 = pHead2;
    // 创建一个map 用节点做key   数据做val  ??
    HashMap<ListNode, Integer> hashMap = new HashMap<>();
    // 将所有元素存入map中
    while(cur1 != null){
        hashMap.put(cur1,cur1.val);
        cur1 = cur1.next;
    }
    // 遍历第二个链表
    while(cur2 != null){
        // 如果存在就直接返回公共子节点
       if (hashMap.containsKey(cur2)){
            return cur2;
        }
        cur2 = cur2.next;
    }
    return null;
}
java 复制代码
/**
 * 方法2:通过集合来辅助查找
 *
 * @param headA
 * @param headB
 * @return
 */
public static ListNode findFirstCommonNodeBySet(ListNode headA, ListNode headB) {
    // 集合这里可以想到的set啦🤩(毕竟是存在重复特性的)
    // 先判断参数  set 不能直接用set 需要使用hashset
    Set<ListNode> set = new HashSet<>();
    // 遍历一个链表 将他存入set集合中
    while (headA != null) {
        set.add(headA);
        headA = headA.next;
    }
    // 遍历第二个链表找出 相同的节点
    while (headB != null) {
    //  if (!set.add(headB)){
    //      return headB;
    //  }  利用set特性
        if(set.contains(headB)){
            return headB;
        }
        headB = headB.next;
    }
    return null;

}

使用栈来实现

思路:这里采用两个栈,分别将两个链表存入栈中,然后一边出栈,一边比较,找到最晚出栈的那一组就是这两个链表的公共子节点。

java 复制代码
/**
 * 方法3:通过栈
 */
public static ListNode findFirstCommonNodeByStack(ListNode headA, ListNode headB) {
   // 参数校验
   /* if(headA == null || headB == null){
        return null;
    }*/
    // 创建连个栈
    Stack<ListNode> stack1 = new Stack();
    Stack<ListNode> stack2 = new Stack();
    // 分别存储两个链表
    while(headA != null){   // 这里参数校验过  前面的校验就可以省掉
        stack1.push(headA);
        headA = headA.next;
    }
    while (headB != null){
        stack2.push(headB);
        headB = headB.next;
    }
    // 出栈 遍历 找到目标
    ListNode ans = null;
    while (stack1.size() > 0 && stack2.size() > 0){
        if (stack1.peek() == stack2.peek()){
            ans = stack1.pop();
            stack2.pop();
        }else {
            break;
        }

    }
    return ans;
}
相关推荐
dialect_4 小时前
KMP算法
开发语言·c++·算法
reikocao4 小时前
卡尔曼滤波的动态机制:P如何改变融合权重
算法
漂流瓶jz5 小时前
UVA-1612 猜名次 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·排序·aoapc·算法竞赛入门经典
吞下星星的少年·-·5 小时前
Div.2 CF 1130B题(构造,贪心)
算法·贪心·构造
是main不是漫7 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
深圳市快瞳科技有限公司8 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查
专注仿真9 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
小豆庄9 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11
Tisfy10 小时前
LeetCode 3882.网格图中最小异或路径:动态规划
算法·leetcode·动态规划
D e re k ZH11 小时前
P5025 [SNOI2017] 炸弹
c++·算法