思路:
两个链表相交,因为链表元素只有一个指针,故相交后,后面都重合了,即相交只能是Y型,不能是X型相交
1、两个链表压入栈中,分别弹出元素,获取最后一个相同的元素即可
2、分别遍历两个链表,获取长度。两个指针,一个先走|len1-len2|步,之后在同步遍历,获取第一个相同的元素即可。
代码:
package com.datastructure.link;
import java.util.Stack;
/*
* 数据结构-单链表之获取链表相交的第一个节点
*/
public class LinkedListGetCommonNode
{
/*
* 元素的基本定义
*/
static class Node{
/*
* value
*/
private int value;
/*
* 链表的下一个元素
*/
private Node next;
public Node (int value) {
this.value = value;
}
@Override
public String toString() {
if (this.next == null) {
return String.valueOf(this.value);
}
return this.value + "->" + this.next.toString();
}
}
/*
* 获取单链表的第一个交点
* 如果两个链表相交,因为链表的指针只有一个,所以相交后,后面的节点必定重合,因此相交只能是Y型,而不是X型
*
* node0->node1->node5->node6
* node2->node3->node5->node6
*
* 思路:分别把两个链表压入栈中,弹出元素,最后一个相同的元素即为第一个交点
*
* 分析:此方式简单易行,需要遍历两次(两个链表+一次栈寻找);但是需要借助额外空间,需要优化
*/
public static Node getCommonNodeByStack(Node node1, Node node2) {
if(node1 == null || node2 == null) {
return null;
}
Stack<Node> stack1 = new Stack<>();
while (node1 != null) {
stack1.push(node1);
node1 = node1.next;
}
Stack<Node> stack2 = new Stack<>();
while (node2 != null) {
stack2.push(node2);
node2 = node2.next;
}
Node commonNode = null;
while (!stack1.empty() && !stack2.empty()) {
Node pop1 = stack1.pop();
Node pop2 = stack2.pop();
if ( pop1 == pop2) {
commonNode = pop1;
} else {
break;
}
}
return commonNode;
}
/*
* 获取单链表的第一个交点
* 如果两个链表相交,因为链表的指针只有一个,所以相交后,后面的节点必定重合,因此相交只能是Y型,而不是X型
*
* node0->node1->node5->node6
* node2->node5->node6
*
* 思路:分别读取两个链表长度,然后用两个指针分别指向两个链表,长的先走lenMax-lenMin步,元素相等时,则找到第一个相交节点
*
* 分析:此方式简单易行,需要遍历两次(两个链表 + 一次寻找)
*/
public static Node getCommonNode(Node node1, Node node2) {
if (node1 == null || node2 == null) {
return null;
}
// 分别遍历获取长度
int len1 = 0;
Node tmpNode1 = node1;
while (tmpNode1 != null) {
len1++;
tmpNode1 = tmpNode1.next;
}
int len2 = 0;
Node tmpNode2 = node2;
while (tmpNode2 != null) {
len2++;
tmpNode2 = tmpNode2.next;
}
// 赋值快慢指针
Node fast = null;
Node low = null;
int num = 0;
if (len1 >= len2) {
fast = node1;
low = node2;
num = len1 - len2;
} else {
fast = node2;
low = node1;
num = len2 - len1;
}
// fast 指针 先走num步
for (int i=0; i< num; i++) {
fast = fast.next;
}
while (fast != null && low != null) {
if (fast == low) {
return fast;
}
fast = fast.next;
low = low.next;
}
return null;
}
public static void main(String args[]) {
Node node1 = new Node(11);
Node node2 = new Node(12);
node1.next = node2;
Node head1 = createTestLinkedList(7, node1);
Node head2 = createTestLinkedList(8, node1);
// 链表相交
System.out.println("link common node: " + getCommonNodeByStack(head1, head2));
// 链表相交
System.out.println("link common node: " + getCommonNode(head1, head2));
}
private static Node createTestLinkedList(int n, Node addNode) {
Node head = new Node(0);
Node curNode = head;
for (int i = 1; i < n; i++) {
curNode.next = new Node(i);
curNode = curNode.next;
}
curNode.next = addNode;
return head;
}
}