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

两个链表公共子节点问题

题目:

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

如果两个链表没有交点,返回 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;
}
相关推荐
SylviaW0824 分钟前
python-leetcode 37.翻转二叉树
算法·leetcode·职场和发展
h^hh34 分钟前
洛谷 P3405 [USACO16DEC] Cities and States S(详解)c++
开发语言·数据结构·c++·算法·哈希算法
玦尘、34 分钟前
位运算实用技巧与LeetCode实战
算法·leetcode·位操作
重生之我要成为代码大佬40 分钟前
Python天梯赛10分题-念数字、求整数段和、比较大小、计算阶乘和
开发语言·数据结构·python·算法
Best_Me071 小时前
【CVPR2024-工业异常检测】PromptAD:与只有正常样本的少样本异常检测的学习提示
人工智能·学习·算法·计算机视觉
HBryce241 小时前
缓存-算法
算法·缓存
eso19832 小时前
Spark MLlib使用流程简介
python·算法·spark-ml·推荐算法
夏末秋也凉2 小时前
力扣-回溯-93 复原IP地址
算法·leetcode
Erik_LinX2 小时前
算法日记27:完全背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
算法·深度优先
AC使者2 小时前
D. C05.L08.贪心算法入门(一).课堂练习4.危险的实验(NHOI2015初中)
算法·贪心算法