160. 相交链表

160. 相交链表 - 力扣(LeetCode)

二刷

class solution {
  int listlength(listnode *head) {
    int length = 0;
    while (head) {
      ++length;
      head = head->next;
    }
    return length;
  }
public:
  listnode *getintersectionnode(listnode *heada, listnode *headb) {
    int lengtha = listlength(heada);
    int lengthb = listlength(headb);
    int diff = std::abs(lengtha - lengthb);
    if (lengtha > lengthb)
      while (diff--)
        heada = heada->next;
    else
      while (diff--)
        headb = headb->next;
    while (heada != headb) {
      heada = heada->next;
      headb = headb->next;
    }
    return heada;
  }
};

要我说我这个怎么就不是 \(\mathrm O(n+m)\) 了?不就是常数大了一倍吗?嗯?但是说实话官解真有点厉害的,这个思路太精妙了,其实就是利用了两个相同的数相加必定是偶数的原理,管你是奇是偶,先走两遍再说。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
};

但是这个 unordered_set 解法也还是得考虑考虑:其实在这道题里,先后遍历(而不是硬要求所谓的双指针一次遍历)是更好的选择。它比较直观,而且省去了一些 contains() 的调用,理论上来说常数要更小一些。

class Solution {
public:
  ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    unordered_set<ListNode *> Visited;
    while (headA) {
      Visited.insert(headA);
      headA = headA->next;
    }
    while (headB) {
      if (Visited.contains(headB))
        return headB;
      headB = headB->next;
    }
    return {};
  }
};

三刷

class Solution {
public:
  ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode *CurA = headA, *CurB = headB;
    while (CurA || CurB) {
      if (!CurA)
        CurA = headB;
      if (!CurB)
        CurB = headA;
      if (CurA == CurB)
        return CurA;
      CurA = CurA->next;
      CurB = CurB->next;
    }
    return nullptr;
  }
};

上面写的都是什么破玩意,我这写得多好。