Nowcoder java-两个链表的第一个公共结点
(题目来自牛客网)
思路
方法一:
通过使用栈,从栈顶取元素,直到找到最后一个相同的点。栈的特点是先入后出,如果两条链有交点,那么交点及其交点之后都是公共的(因为next指针只有一个),从后往前找即可。
时间复杂度O(m+n),空间复杂度O(m+n)。
方法二:
利用HashSet,遍历链表1,把链表1中的元素添加到hashSet中,在遍历链表2,看hashSet中是否包含链表2的元素,如果存在,那么就是交点,返回即可,如果不包含,则继续遍历链表2。
时间复杂度O(m+n),空间复杂度O(m或者n) (m、n中较大的那个)
方法三:
找出2个链表的长度,然后让长的先走两个链表的长度差,然后再一起走(因为2个链表用公共的尾部)。时间复杂度O(m+n),空间复杂度O(1)
代码
import java.util.HashSet;
import java.util.Stack;
public class FindFirstCommonNode {
// 方法一:使用栈结构,从栈顶拿出元素进行比较。(从两个链表的后面开始比较)
// public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// if (pHead1 == null || pHead2 == null) {
// return null;
// }
// Stack<ListNode> stack1 = new Stack<>();
// Stack<ListNode> stack2 = new Stack<>();
//
// while (pHead1 != null) {
// stack1.push(pHead1);
// pHead1 = pHead1.next;
// }
// while (pHead2 != null) {
// stack2.push(pHead2);
// pHead2 = pHead2.next;
// }
//
// ListNode commonList = null;
// while (!stack1.isEmpty() && !stack2.isEmpty() && stack1.peek() == stack2.peek()) {
// stack2.pop();
// commonList = stack1.pop();
// }
// return commonList;
// }
//方法二:利用HashSet求解
// public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// ListNode current1 = pHead1;
// ListNode current2 = pHead2;
// HashSet<ListNode> hashSet = new HashSet<>();
// while (current1 != null) {
// hashSet.add(current1);
// current1 = current1.next;
// }
// while (current2 != null) {
// if (hashSet.contains(current2)) {
// return current2;
// }
// current2 = current2.next;
// }
// return null;
// }
//方法三:通过求长度差,长的先走,走完两个链表的长度差再一起走,直到两个遇到的是同一个数
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);
if (length1 >= length2) {// 如果链表1的长度大于链表2的长度
int len = length1 - length2;
while (len > 0) {// 先遍历链表1,遍历的长度就是两链表的长度差
current1 = current1.next;
len--;
}
}
if (length1 < length2) {//如果链表2的长度大于链表1的长度
int len = length2 - length1;
while (len > 0) {// 先遍历链表2,遍历的长度就是两链表的长度差
current2 = current2.next;
len--;
}
}
while (current1 != current2) { //开始齐头并进,直到找到第一个公共结点
current1 = current1.next;
current2 = current2.next;
}
return current1;
}
public static int getLength(ListNode pHead) {// 求指定链表的长
int length = 0;
ListNode current = pHead;
while (current != null) {
length++;
current = current.next;
}
return length;
}
public static void main(String[] args) {
ListNode pHead1 = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(6);
ListNode node4 = new ListNode(7);
ListNode pHead2 = new ListNode(4);
ListNode node5 = new ListNode(5);
pHead1.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
pHead2.next = node5;
node5.next = node3;
node3.next = node4;
System.out.println(new FindFirstCommonNode().findFirstCommonNode(pHead1, pHead2));
}
}