题目
两个有交叉的单链表,求交叉点
方案描述
- 求出两个链表的长度
- 先遍历长链表到和短链表长度相同的位置
- 同时遍历两个链表,知道有相同的节点位置
代码实现
- MyLIst类:
/**
* 定义链表类
* @author xxx
* @date 2018/7/4
*/
public class MyList {
private int length = 0;
private ListNode headerNode;
private ListNode tailNode;
public void add(ListNode listNode){
if (length == 0){
length++;
headerNode = listNode;
tailNode = listNode;
tailNode.setNextNode(null);
return;
}
length++;
tailNode.setNextNode(listNode);
tailNode = listNode;
tailNode.setNextNode(null);
}
public void add(MyList myList){
if (null == myList || myList.length == 0){
return;
}
length += myList.getLength();
this.getTailNode().setNextNode(myList.getHeaderNode());
this.setTailNode(myList.getTailNode());
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public ListNode getHeaderNode() {
return headerNode;
}
public void setHeaderNode(ListNode headerNode) {
this.headerNode = headerNode;
}
public ListNode getTailNode() {
return tailNode;
}
public void setTailNode(ListNode tailNode) {
this.tailNode = tailNode;
}
@Override
public String toString() {
return "MyList{" +
"length=" + length +
", headerNode=" + headerNode +
", tailNode=" + tailNode +
'}';
}
}
- ListNode类:
/**
* list节点
* @author xxx
* @date 2018/7/4
*/
public class ListNode {
private int data;
private ListNode nextNode;
public ListNode(int data){
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public ListNode getNextNode() {
return nextNode;
}
public void setNextNode(ListNode nextNode) {
this.nextNode = nextNode;
}
@Override
public String toString() {
return "ListNode{" +
"data=" + data +
", nextNode=" + nextNode +
'}';
}
}
- 创建长度为n的方法List方法(为了区别各个节点内容,添加了基础值):
private static MyList createList(int length, int firstNum){
if (length <= 0){
return null;
}
MyList myList = new MyList();
for (int n = 0; n < length; n++){
ListNode listNode = new ListNode(firstNum+n+1);
myList.add(listNode);
}
return myList;
}
- 拼接List方法:
private static void plusList(MyList myList1, MyList myList2){
if (null == myList1 || myList1.getLength() == 0){
myList1 = myList2;
}
myList1.add(myList2);
}
- 获取交叉点方法:
public static ListNode getCrossingNode(MyList myList1, MyList myList2){
int listLength1 = myList1.getLength();
int listLength2 = myList2.getLength();
ListNode headNode1 = null;
ListNode headNode2 = null;
if (listLength1 > listLength2){
headNode1 = myList1.getHeaderNode();
headNode2 = myList2.getHeaderNode();
}else {
headNode1 = myList2.getHeaderNode();
headNode2 = myList1.getHeaderNode();
}
for (int n = 0; n < Math.abs(listLength1 - listLength2); n++){
headNode1 = headNode1.getNextNode();
}
while (null != headNode1 && null != headNode2 && headNode1.getData() != headNode2.getData()){
headNode1 = headNode1.getNextNode();
headNode2 = headNode2.getNextNode();
}
System.out.println(headNode1.getData());
System.out.println(headNode2.getData());
return headNode1;
}
- 测试方法:
public static void main(String[] args) {
MyList myList1 = createList(10, 0);
System.out.println(myList1);
MyList myList2 = createList(8, 100);
System.out.println(myList2);
MyList myListCrossing = createList(5, 1000);
System.out.println(myListCrossing);
plusList(myList1, myListCrossing);
plusList(myList2, myListCrossing);
System.out.println(myList1);
System.out.println(myList2);
getCrossingNode(myList1, myList2);
}