两个链表公共子节点问题
题目:
这是一道非常经典的链表题目,也属于常考的问题。 已知:两个链表,找到相交点 注意:
如果两个链表没有交点,返回 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;
}