几天不见,甚是想念,这几天小编也是浅浅的鸽了一下~本篇文章也是是单向链表例题的压轴文章(也就是导数第二篇~),话不多说,进入今天的正题叭~
1.输入两个链表,找出它们的第一个公共结点
在看到这个题的第一反应,我们首先要想的是,两个链表相交,是什么类型的?两个节点相交,相交后面的节点怎么办,是“X”型还是“Y”型?其实是“Y”我们还是借助图片来理解
注意 :链表相交是地址,不是元素!
那么,如何找到这个交点呢
1.我们先定义两个cur,让两个cur分别等于两个链表的头节点
2.让两个cur每次分别走一步
3.此时两cur相遇的节点就是相交的节点
如图
其实,仔细想想就不难发现以上理论是经不起推敲的,因为在交点之前,都刚好有两个节点,一人走一步的情况才能刚好找到交点(路程一样,速度一样)
如果一个交点前是三个节点,一个交点前是两个节点,又该怎么办呢
如图
链表1长度为5(3+2)链表2为4(2+2),我们只需两个链表相减,得到差值1(5-4),先让长的先走差值步,在以同样的速度走,即可
注意:我们也不要忘了先确定那个链表长,或者一个链表为空,一个不为空的情况
代码如下
public static MySingleList.ListNode getIntersectionNode(MySingleList.ListNode headA,
MySingleList.ListNode headB) {
//1、分别求2个链表的长度
int lenA = 0;
int lenB = 0;
MySingleList.ListNode pL = headA;//假设pL 所指向的链表 是最长的链表
MySingleList.ListNode pS = headB;//假设pS 所指向的链表 是最短的链表
while(pL != null) {
lenA++;
pL = pL.next;
}
while(pS != null) {
lenB++;
pS = pS.next;
}
pL = headA;
pS = headB;
//分别求得了 2个链表的长度
int len = lenA - lenB;
//修正指向 和 len的差值
if(len < 0) {
pL = headB;
pS = headA;
len = lenB - lenA;
}
//让最长的链表 先走差值步
while(len != 0) {
pL = pL.next;
len--;
}
//3、就是相遇的点
while(pL != pS) {
pL = pL.next;
pS = pS.next;
}
return pL;
}
调用测试
private static void createIntersect(MySingleList.ListNode headA,
MySingleList.ListNode headB) {
headB.next.next = headA.next.next;
}
public static void main(String[] args) {
MySingleList mySingleList = new MySingleList();
mySingleList.addLast(12);
mySingleList.addLast(23);
mySingleList.addLast(34);
mySingleList.addLast(45);
mySingleList.addLast(56);
mySingleList.display();
MySingleList mySingleList1= new MySingleList();
mySingleList1.addLast(8);
mySingleList1.addLast(15);
mySingleList1.addLast(30);
mySingleList1.addLast(40);
mySingleList1.addLast(78);
mySingleList1.display();
createIntersect(mySingleList.head,mySingleList1.head);
MySingleList.ListNode ret = getIntersectionNode(mySingleList.head,mySingleList1.head);
System.out.println(ret.val);
}
运行截图
2.给定一个链表,判断链表中是否有环。
什么是有环呢,话不多说,上图
那么,我们可以理解为,两个人同时跑,一快一慢,快的先跑到环里之后,开始在环里转圈,此时,慢的也进环了,由于,快的已经在环里跑了,如果两个相遇即证明有环,如图(这里有点绕,大家注意理解)
快的速度是慢的两倍(只有这种情况是合理的,条件不合理否则容易跳过)
比如,一个走一步,一个走三步,这种情况就永远不会相遇
两个速度只能差一步
fast:2 slow:1
其实本质就是一个追击问题,每次追一步总能追上
注意:不要忘记为空的情况
代码如下
public boolean hasCycle() {
if(head == null) return false;
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
return true;
}
}
return false;
}
测试调用
这里我们先手动将链表变为有环链表,代码如下
这个过程很简单,只需让最后一个节点的next域等于前面的某一节点即可
public void createLoop() {
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = head.next;
}
下面我们进行调用
public static void main(String[] args) {
MySingleList mySingleList = new MySingleList();
mySingleList.addLast(12);
mySingleList.addLast(23);
mySingleList.addLast(34);
mySingleList.addLast(45);
mySingleList.addLast(56);
mySingleList.display();
mySingleList.createLoop();
mySingleList.hasCycle();
System.out.println(mySingleList.hasCycle());
}
运行截图
由于今天的文章稍难,所以我们今天只介绍两道题,剩下的两道题我们下一篇文章再继续介绍,敬请期待叭~觉着小编将的好的可以点点关注~我们下期再见