代码随想录链表篇——链表相交(三种方法)

题目

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
在这里插入图片描述

思路

1.差值步法
这个方法的思路为先定义两个指针nodeA,nodeB,分别指向两条链表的头节点,再一人一步往后走,如果这两条链表有相交,则两个指针必定会相遇,若没有相遇则返回null,说明两条链表没有相交。

但是上述情况是在两条链表长度相等的情况下,若这两条链表不相等怎么办呢?

可以先找到两条链表中较长的那条,让指向长链表的那个头指针先走它们两个链表的长度差值步数,然后两指针再一起往前走,若相遇则说明两条链表相交。

注意:只需要找到链表相交的起始节点即可,并不是找链表重合,二者概念不一样,相交只要有指针指向相同即可,而重合则是起点到终点所有内容相同。

java代码

class Solution{
	public ListNode getIntersectionNode(ListNode headA,ListNode headB){
		ListNode nodeA = headA;
		ListNode nodeB = headB;
		int lenA = 0,lenB = 0;
		int gap = 0;
		while(nodeA != null){// 求链表A的长度
			lenA++;
			nodeA = nodeA.next;
		}
		while(nodeB != null){// 求链表B的长度
			lenB++;
			nodeB = nodeB.next;
		}
        //再将两指针重新指向头节点,因为求长度的时候nodeA、nodeB走到了链表尾
		nodeA = headA;
		nodeB = headB;
		//若链表A长,则nodeA先走长度差步
		if(lenA > lenB){
			gap = lenA - lenB;
			while(gap-- > 0){
				nodeA = nodeA.next;
			}
		}else{//若链表B长,则nodeB先走长度差步
			gap = lenB - lenA;
			while(gap-- > 0){
				nodeB = nodeB.next;
			}
		}

		while(nodeA != null && nodeB != null){//两指针同时走	
			if(nodeA == nodeB){//如果相遇,则代表相交,返回相交节点
				return nodeA;
			}
			//否则继续往后判断
			nodeA = nodeA.next;
			nodeB = nodeB.next;
		}
        //当while循环遍历完时还没相遇,则不存在相交
		return null;		
	}
}

2.双指针法

因为两条链表相交,所以会有一段公共长度(至少为1,哪怕后面不是完全重合),创建两个指针nodeAnodeB分别指向链表A和链表B。

让他们分别循环往前各走一步,当nodeA走完为空时,就让他前往链表B的头节点;nodeB也一样,当它走完时,让它前往A链表的头节点。之后同样继续循环往前走,因为两条链表是相交的,则nodeA和nodeB必然会相遇(走的总长度相同,即A+B的长度)。

因为两条链表相交时,分为三部分:c部分是固定的,那么不管a部分和b部分谁长,走第二遍时,nodeA走过的路程为a部分长度加上b部分长度;nodeB走过的路程也为a部分长度加上b部分长度。

java代码:

class Solution{
	public ListNode getIntersectionNode(ListNode headA,ListNode headB){
		if(headA == null || headB == null){//有一个链表为空都不可能相交
			return null;
		}
		//创建新的变量指向当前头结点,方便移动,因为移动过程中是需要和头结点初始位置进行比较的,所以需要保持headA和headB不变
		ListNode nodeA = headA;
		ListNode nodeB = headB;
		while(nodeA != nodeB){
			if(nodeA == null){//A链表走完时,继续走B链表
				nodeA = headB;
			}else{
				nodeA = nodeA.next;	
			}
			if(nodeB == null){//B链表走完时,继续走A链表
				nodeB = headA;
			}else{
				nodeB = nodeB.next;
			}
		}
		return nodeA;
	}
}

3.哈希集合法

若两条链表相交,则至少一个完全相同的节点,可以先遍历链表A,将其所有的节点记录下来,然后遍历链表B,若链表B中存在一个及以上和链表A中一样的节点,那么就说明这两条链表相交了,反之则未相交。

使用哈希集合来存储节点,遍历链表B的节点时,依次判断该节点是否在哈希集合中

java代码:

class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //定义一个哈希集合set
        Set<ListNode> set = new HashSet<>();
        //遍历链表A,将其节点全部存入哈希集合中
        while(headA != null){
            set.add(headA);
            headA = headA.next;
        }
        //遍历链表B各个节点,若该节点在集合中存在则说明相交
        while(headB != null){
            if(set.contains(headB)){//如果包含了相交的节点
                return headB;//则直接返回
            }
            headB = headB.next;
        }
        //循环遍历完说明并没有节点在集合中存在,即不相交
        return null;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HDU-五七小卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值