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

两个链表公共子节点问题

题目:

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

如果两个链表没有交点,返回 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;
}
相关推荐
风中的微尘2 小时前
39.网络流入门
开发语言·网络·c++·算法
西红柿维生素3 小时前
JVM相关总结
java·jvm·算法
ChillJavaGuy4 小时前
常见限流算法详解与对比
java·算法·限流算法
sali-tec4 小时前
C# 基于halcon的视觉工作流-章34-环状测量
开发语言·图像处理·算法·计算机视觉·c#
你怎么知道我是队长6 小时前
C语言---循环结构
c语言·开发语言·算法
艾醒6 小时前
大模型面试题剖析:RAG中的文本分割策略
人工智能·算法
纪元A梦8 小时前
贪心算法应用:K-Means++初始化详解
算法·贪心算法·kmeans
_不会dp不改名_8 小时前
leetcode_21 合并两个有序链表
算法·leetcode·链表
mark-puls8 小时前
C语言打印爱心
c语言·开发语言·算法
Python技术极客8 小时前
将 Python 应用打包成 exe 软件,仅需一行代码搞定!
算法