令人头秃的LeetCode——160. 相交链表

题目链接:160. 相交链表


解法一 暴力法(结合哈希表)

思路

暴力求解,不带想的~

  • 创建一个哈希表HashSet<ListNode>用于存放节点的地址。
  • 遍历headA指向的链表,将每个节点的地址存放在哈希表中。
  • 遍历headB指向的链表,判断当前节点的地址是否已在哈希表中出现。若出现,遍历结束。
  • 返回headB
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        HashSet<ListNode> set = new HashSet<>();
        while (headA != null){
            set.add(headA);
            headA = headA.next;
        } 
        while (headB != null && !set.contains(headB))
            headB = headB.next;
        return headB;
    }

复杂度分析

  • 时间复杂度:O(m+n),m和n分别为两链表的长度。
  • 空间复杂度:O(m) / O(n),取决于哈希表存放哪个链表的值。

解法二 双指针(对齐起点)

思路

由于两个链表的长度不一致,若两个指针同时出发,我们想要比较的两个节点之间一定存在一个长度差。因此,我们需要想办法获取这个长度差,手动对齐起点。怎么获取到这个长度差呢?遍历咯!😂

  • 分别遍历两个链表,获取他们的长度,分别表示为lenAlenB
  • 获取长度差diff = abs(lenA - lenB)
  • 长链表的头指针先向后移动diff次,对齐起点。
  • 接着,遍历两个链表,比较节点地址是否相同。若相同,遍历结束。
  • 返回headAheadB
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lenA = getLen(headA);
        int lenB = getLen(headB);
        return getIntersectionNode(headA, headB, lenA - lenB);
    }

    private static int getLen(ListNode head){
        ListNode cur = head;
        int len = 0;
        while (cur != null){
            len ++;
            cur = cur.next;
        }
        return len;
    }

    private static ListNode getIntersectionNode(ListNode a, ListNode b, int diff){
        if (diff >= 0){
            for (; diff > 0; diff --) 
                a = a.next;
            while(a != null && a != b){
                a = a.next;
                b = b.next;
            }
        }else {
            for (; diff < 0; diff ++) 
                b = b.next;
            while(b != null && b != a){
                a = a.next;
                b = b.next;
            }
        }
        return a;      
    }

复杂度分析

  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)

解法三 双指针(骚操作——链表拼接)

思路

解法二的风骚操作,目的仍然是对齐起点。

  • 在短链表遍历到空的时候,将长链表接在短链表后面,继续遍历。

  • 对于长链表相似的在遍历到空的时候,将短链表接在其后面,继续遍历。

  • 这样,若存在相交的节点,两者的指针一定会在此节点相遇。

  • 为什么呢?

  • img

  • 如图,假设lenB >= lenA,长度差为diff,则b1 = diff。假设距离交点的长度为X,即[a1,a2] = [b2,b3] = X,相交部分的长度为Y,即[c1,c2,c3] = Y,则短链表的长度构成为lenA = X + Y,长链表的长度构成为lenB = diff + X + Y

  • 那么,链表拼接后遍历,啥时候两指针相遇呢?

  • lenA + lenB = (X + Y + diff) + X + Y
    lenB + lenA = (diff + X + Y) + X + Y
    
  • 没错,神奇的在距离交点的长度为X的地方相遇了,换言之,起点被对齐了,解法二的核心问题就被解决了!

  • 接下来,同解法二

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        while (curA != curB){
            curA = curA == null ? headB : curA.next;
            curB = curB == null ? headA : curB.next;
        }
        return curA;
    }

复杂度分析

  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)

小结

能想到解法三的都是人才哦~

我咋想不到呢~(#`-_ゝ-)

哎 你他娘的还真是个天才_他娘_天才_真是表情

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页