转载地址:http://blog.csdn.net/litoupu/article/details/41555557
查找两个链表的第一个公共节点,如果两个节点的尾节点相同,肯定存在公共节点,换句话说,尾结点不相同肯定没有公共结点。
方法: 长的链表开始多走 (h1的数量 - h2的数量)步,然后和短链表同步往下走,遇到的第一个相同的节点就是最早的公共节点
原理是 如果链表有公共部分,那么公共部分长度肯定相等,所以二个链表从最后一个元素开始编号,公共起点 编码必须相等。
如果先让长的链表 先走多出来的长度,二个链表就可以同步寻找公共结点了。
- /**
- * Definition for singly-linked list.
- * public class ListNode {
- * int val;
- * ListNode next;
- * ListNode(int x) {
- * val = x;
- * next = null;
- * }
- * }
- */
- public class Solution {
- public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
- if(headA == null ||headB == null)return null;
- ListNode h1 = headA;
- ListNode h2 = headB;
- int count1 = 1, count2 = 1;
- while(h1.next != null){
- count1++;
- h1 = h1.next;
- }
- while(h2.next != null){
- count2++;
- h2 = h2.next;
- }
- if(h1 != h2) return null;
- else{
- int count = Math.abs(count1 - count2);
- if(count2 > count1){
- h1 = headB;
- h2 = headA;
- }
- else{
- h1 = headA;
- h2 = headB;
- }
- while((count--) > 0){
- h1 = h1.next;
- }
- while(h1 != null&&h2 != null && h1 != h2){
- h1 = h1.next;
- h2 = h2.next;
- }
- return h1;
- }
- }
- }
该问题求两个单链表(不存在环)相交的第一个节点,若不相交返回null。
算法分析:
step1: 把headA的尾同headB相连接
判断headA是否同headB相交就可转换成判断headA中是否存在环。
通过slow,fast两个指针遍历headA,slow移动一步,fast移动两步。若存在环,则slow,fast会指向一个相同的地址,称之为碰撞点p.
若不存在环,即fast == null or fast.next == null
step2: 若存在环,则从headA的第一个节点和碰撞点,每次移动一步,则他们相交的时候就是两个链表相交的一个节点。
如图所示,若fast,slow在碰撞点为p,假设环的长度为r,整个链表长度为L,LA之间的长度为a,AP之间的长度p。
若slow走了s步,则fast = 2s。
显然存在 2s = s + n*r ---> s = n*r=(n-1)*r+L-a.
而s = a+p,带入式子,可得a = (n-1)*r+L-a-p.注意到L-a-p这段距离就是碰到点到相交点的距离,也就是说,从链表第一个节点,碰撞点同时遍历,他们必定会在第一个相交的点碰撞。
注意:最后还需要断开headA与headB。
- public class IntersectionNode {
- public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
- if (headA == null || headB == null)
- return null;
- ListNode p, q, tmp;
- // step1 把headB链接在headA后
- p = headA;
- while (p.next != null)
- p = p.next;
- tmp = p;
- p.next = headB;
- // step2 找到碰撞点
- p = headA;
- q = headA;
- while (q != null && q.next != null) {
- p = p.next;
- q = q.next.next;
- if (p == q) {
- break;
- }
- }
- if (q == null || q.next == null) {
- tmp.next = null;// 切断headA与headB
- return null;
- } else {
- // step3 找到第一个公共节点
- p = headA;
- while (p != q) {
- p = p.next;
- q = q.next;
- }
- tmp.next = null;// 切断headA与headB
- return p;
- }
- }
- //判断链表是否存在环
- public boolean isCircle(ListNode headA) {
- ListNode slow, fast;
- slow = headA;
- fast = headA;
- while (fast != null && fast.next != null) {
- slow = slow.next;
- fast = fast.next.next;
- if (slow == fast) {
- break;
- }
- }
- if (fast == null || fast.next == null)
- return false;
- else {
- return true;
- }
- }
- //通过数组创建链表
- public ListNode createListNodeFromArray(int[] array) {
- ListNode head = new ListNode(array[0]);
- ListNode tmp = head;
- for (int i = 1; i < array.length; i++) {
- ListNode node = new ListNode(array[i]);
- tmp.next = node;
- tmp = node;
- }
- return head;
- }
- //打印
- public void print(ListNode headA) {
- ListNode p = headA;
- while (p != null) {
- System.out.print(p.val + " ");
- p = p.next;
- }
- p = null;
- }
- public static void main(String[] args) {
- IntersectionNode intersection = new IntersectionNode();
- int[] arrayA = { 1, 3, 5, 7, 9 };
- int[] arrayB = { 2, 4, 6, 8, 10 };
- int[] arrayC = { 11, 12, 13 };
- ListNode headA = intersection.createListNodeFromArray(arrayA);
- ListNode headB = intersection.createListNodeFromArray(arrayB);
- ListNode headC = intersection.createListNodeFromArray(arrayC);
- //headA同headC相连
- ListNode p = headA;
- while (p.next != null)
- p = p.next;
- p.next = headC;
- intersection.print(headA);
- //headB同headC相连
- p = headB;
- while (p.next != null)
- p = p.next;
- p.next = headC;
- //headA与headB相交
- ListNode node = intersection.getIntersectionNode(headA, headB);
- System.out.println(node.val);
- }
- }