今天是秋招预备队第六天,今天有点摆烂,但是算法不能断!!今天也要写两道题
打卡失败,今天就干了一道题
问题1:两个链表的第一个公共结点
描述:
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:n≤1000
要求:空间复杂度 O(1),时间复杂度 O(n)
解题方法:
1、hash表
1)将一个链表的所有节点存入hash表
2)遍历第二个链表,判断当前节点是否存在于hash表
3)如果遍历完第二个链表都没找到存在的节点,则不存在公共节点,如果存在公共节点,
则hash表中一定存在当前节点,并且遍历出的第一个存在节点就是第一个公共节点
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
//hash表
Set<ListNode> hashSet = new HashSet<ListNode>();
//将pHead1存入hash表
while(pHead1 != null){
hashSet.add(pHead1);
pHead1 = pHead1.next;
}
//遍历怕pHead2,判断其是否与pHead1有公共节点
while(pHead2 != null){
//遍历到第一个公共节点,返回该节点
if(hashSet.contains(pHead2)){
return pHead2;
}
pHead2 = pHead2.next;
}
//不存在公共节点
return null;
}
}
时间复杂度:O(n+m),最坏遍历完两个链表的长度
空间复杂度:O(n),需要将一个链表长度为n的链表存储
2、双指针
例子如下:
1)使用两个指针N1,N2,一个从链表1的头节点开始遍历,我们记为N1,一个从链表2的头节点开始遍历,我们记为N2。
2)让N1和N2一起遍历,当N1先走完链表1的尽头(为null)的时候,则从链表2的头节点继续遍历,同样,如果N2先走完了链表2的尽头,则从链表1的头节点继续遍历,也就是说,N1和N2都会遍历链表1和链表2。
3)因为两个指针,同样的速度,走完同样长度(链表1+链表2),不管两条链表有无相同节点,都能够到达同时到达终点。(N1最后肯定能到达链表2的终点,N2肯定能到达链表1的终点)。
4)所以,如何得到公共节点:
- 有公共节点的时候,N1和N2必会相遇,因为长度一样嘛,速度也一定,必会走到相同的地方的,所以当两者相等的时候,则会第一个公共的节点
- 无公共节点的时候,此时N1和N2则都会走到终点,那么他们此时都是null,所以也算是相等了。
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
//遍历指针
ListNode l1 = pHead1, l2 = pHead2;
//当两指针未相遇时,移动指针
while(l1 != l2){
//遍历一遍其中链表,遍历完后遍历另一个链表
l1 = (l1==null)?pHead2:l1.next;
l2 = (l2==null)?pHead1:l2.next;
}
//返回相遇点或者链表尾节点
return l1;
}
}
时间复杂度:O(m+n), m,n分别为链表A,B的长度,最坏情况下,公共结点为最后一个,需要遍历m+n个结点
空间复杂度:O(1)