牛客网在线编程专题《剑指offer-面试题37》两个链表的第一个公共结点

本文介绍了一种高效算法,用于查找两个链表的第一个公共节点。通过先计算两链表长度,确定较长链表,然后调整遍历起点,最终同步遍历两链表直至找到首个相同节点。此算法时间复杂度为O(m+n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=13&tqId=11189&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路:

首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同时在两个链表上遍历,找到的第一个相同的结点就是它们的第一个公共结点。

如上图所示的两个链表中,我们可以先遍历一次得到它们的长度分别为5和4,也就是较长的链表与较短的链表相比多一个结点。第二次先在长的链表上走1步,到达结点2。接下来分别从结点2和结点4出发同时遍历两个结点,直到找到它们第一个相同的结点6,这就是我们想要的结果。

时间复杂度为O(m+n)。

已经AC的代码:

public class firstCommonNode {
	
	class ListNode{
		int val;
		ListNode next = null;
		
		public ListNode(int val) {
			// TODO Auto-generated constructor stub
			this.val = val;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		firstCommonNode ownClass = new firstCommonNode();
		ListNode l1_one = ownClass.new ListNode(1);
		ListNode l1_two = ownClass.new ListNode(2);
		l1_one.next = l1_two;
		ListNode l1_thr = ownClass.new ListNode(3);
		l1_two.next = l1_thr;
		ListNode l1_for = ownClass.new ListNode(6);
		l1_thr.next = l1_for;
		ListNode l1_fiv = ownClass.new ListNode(7);
		l1_for.next = l1_fiv;
		
		ListNode l2_one = ownClass.new ListNode(4);
		ListNode l2_two = ownClass.new ListNode(5);
		l2_one.next = l2_two;
		l2_two.next = l1_for;
		
		ListNode node = FindFirstCommonNode(l1_one, l2_two);
		System.out.println(node.val);
	}
	
	public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
		//得到两个链表的长度
		int nLength1 = getListLength(pHead1);
		int nLength2 = getListLength(pHead2);
		//得到两个链表长度之间的差值
		int nLengthDif = nLength1 - nLength2;
		
		ListNode pListHeadLong = null;
		ListNode pListHeadShort = null;
		if(nLengthDif >=0) {
			pListHeadLong = pHead1;
			pListHeadShort = pHead2;
		}else {
			pListHeadLong = pHead2;
			pListHeadShort = pHead1;
			nLengthDif = nLength2 - nLength1;
		}
		
		// 先在长链表上走几步,再同时在两个链表上遍历
		for(int i=0; i<nLengthDif; i++) {
			pListHeadLong = pListHeadLong.next;
		}
		
		// 同时在两个链表上遍历
		while((pListHeadLong != null) && (pListHeadShort != null) && (pListHeadLong != pListHeadShort)) {
			pListHeadLong = pListHeadLong.next;
			pListHeadShort = pListHeadShort.next;
		}
		
		//得到第一个公共结点
		ListNode pFirstCommonNode = pListHeadLong;
		return pFirstCommonNode;
	}
	
	public static int getListLength(ListNode pHead) {
		int nLength = 0;
		ListNode pNode = pHead;
		while(pNode != null) {
			nLength++;
			pNode = pNode.next;
		}
		return nLength;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值