剑指offer算法题
链表
题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
题目分析
方法一
利用hashmap中的元素唯一性,首先将链表1放入hashmap,之后在将链表2与hashmap中存放的链表1进行比对,如果相同,则找到了他们的第一个公共节点。这种方法不用考虑两个链表的长短,直接进行比对即可。
下面是JAVA算法实现:
//注意导入HashMap
import java.util.HashMap;
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode current1 = pHead1;
ListNode current2 = pHead2;
HashMap < ListNode,Integer> hashMap = new HashMap<ListNode , Integer>();
while(current1 !=null){
hashMap.put(current1,null);
current1 = current1.next;
}
while(current2!=null){
if(hashMap.containsKey(current2)){
return current2;
}
current2 = current2.next;
}
return null;
}
方法二
如果两个链表有公共节点,说明从公共节点开始后面的元素都一样。所以先判断两个链表的长短,先将长的链表遍历到与短的链表长度一致的位置,之后在开始齐头并进,直至找到第一个公共节点。
下面是JAVA算法实现:
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode current1 = pHead1;
ListNode current2 = pHead2;
if(pHead1 == null || pHead2 == null){
return null;
}
int length1 = getLength(current1);
int length2 = getLength(current2);
// 两连表的长度差
// 如果链表1的长度大于链表2的长度
if(length1 - length2 >=0){
int len = length1 - length2;
// 先遍历链表1,遍历的长度就是两链表的长度差
while(len >0){
current1 = current1.next;
--len;
}
}else{
// 如果链表2的长度大于链表1的长度
int len = length2 - length1;
// 先遍历链表2,遍历的长度就是两链表的长度差
while(len>0){
current2 = current2.next;
--len;
}
}
//开始齐头并进,直到找到第一个公共结点
while(current1!=current2){
current1 = current1.next;
current2 = current2.next;
}
return current1;
}
// 求指定链表的长度
private static int getLength(ListNode pHead){
int length = 0;
ListNode current = pHead;
while(current != null){
++length;
current = current.next;
}
return length;
}
方法三
- 假定 List1长度: a+n List2 长度:b+n, 且 a<b
- 那么 p1 会先到链表尾部, 这时p2 走到 a+n位置,将p1换成List2头部
- 接着p2 再走b+n-(n+a) =b-a 步到链表尾部,这时p1也走到List2的b-a位置,还差a步就到可能的第一个公共节点。
- 将p2 换成 List1头部,p2走a步也到可能的第一个公共节点。如果恰好p1==p2,那么p1就是第一个公共节点。 或者p1和p2一起走n步到达列表尾部,二者没有公共节点,退出循环。 同理a>=b.
时间复杂度O(n+a+b)
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null){
return null;
}
ListNode curr1 = pHead1, curr2 = pHead2;
while(curr1!=curr2){
curr1 = (curr1 == null ? pHead2: curr1.next);
curr2 = (curr2 == null ? pHead1: curr2.next);
}
return curr1;
}