两个链表的公共子链表Java_【Java】 剑指offer(52) 两个链表的第一个公共结点

本文参考自《剑指offer》一书,代码采用Java语言。

题目

输入两个链表,找出它们的第一个公共结点。

思路

蛮力法:遍历第一个链表的结点,每到一个结点,就在第二个链表上遍历每个结点,判断是否相等。时间复杂度为O(m*n),效率低;

使用栈:由于公共结点出现在尾部,所以用两个栈分别放入两个链表中的结点,从尾结点开始出栈比较。时间复杂度O(m+n),空间复杂度O(m+n)。

利用长度关系:计算两个链表的长度之差,长链表先走相差的步数,之后长短链表同时遍历,找到的第一个相同的结点就是第一个公共结点。

利用两个指针:一个指针顺序遍历list1和list2,另一个指针顺序遍历list2和list1,(这样两指针能够保证最终同时走到尾结点),两个指针找到的第一个相同结点就是第一个公共结点。

测试算例

1.功能测试(有/无公共结点;公共结点分别在链表的中间,头结点和尾结点)

2.特殊测试(头结点为null)

完整Java代码

//题目:输入两个链表,找出它们的第一个公共结点。

public class FirstCommonNodesInLists {

public class ListNode{

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}

//方法1:利用长度关系

public ListNode findFirstCommonNode1(ListNode pHead1, ListNode pHead2) {

int length1 = getLength(pHead1);

int length2 = getLength(pHead2);

int lengthDif = length1-length2;

ListNode longList = pHead1;

ListNode shortList = pHead2;

if(lengthDif<0){

longList = pHead2;

shortList = pHead1;

lengthDif = -lengthDif;

}

for(int i=0;i

longList = longList.next;

while(longList!=null && longList!=shortList ){

longList=longList.next;

shortList=shortList.next;

}

return longList; //没有公共结点刚好是null

}

private int getLength(ListNode head){

int len=0;

while(head!=null){

len++;

head=head.next;

}

return len;

}

//方法2:两个指针,p1顺序遍历list1和list2;p2顺序遍历list2和list1;最终一定会相遇

public ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) {

ListNode p1=pHead1;

ListNode p2=pHead2;

while(p1!=p2){

p1= p1==null ? pHead2 : p1.next;

p2= p2==null ? pHead1 : p2.next;

}

return p1;

}

}

收获

1.由于有共同结点时,后面的链表是重合的,所以这道题关键是要保证最后同时遍历到达尾结点,因此就有了后面三种方法:

利用栈的先进后出实现同时到达;

利用长度关系,长链表先行几步,实现同时到达;

两个指针同时遍历两个链表,一个先list1后list2,另一个则相反,也可以实现同时到达。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值