被裁了!刚刚谈完话 有两个选择,怎么选?
刚刷到这个帖子,我第一反应是:这 HR 话术还挺熟。
人刚被裁,谈完话就丢两个选项过来。一个是你人还挂着,按点来按点走,月底再走,中间自己找工作。另一个是直接拿 N+1,钱多一点,但离职证明上会写清楚是被裁。
HR 还说之前大家都选第一个,意思差不多就是:你也别搞特殊,离职证明好看点。听着像为你好,其实打工人都懂,最关键的还是钱和下一份工作怎么衔接。
现在这环境,被裁真不是什么见不得人的事。公司缩编、业务砍线、预算没了,这些面试里一说,正常公司也能听懂。反倒是少拿两个月工资,只为了一个“看起来体面”的说法,我觉得有点亏。
我会倾向选 2。钱先拿到手,别被一句“以前大家都这么选”带跑。离职证明这东西重要,但也没重要到值两个月工资吧。
链表相交,不是节点值一样就算相交
链表相交这题,最容易写错的地方不是算法,而是把“值相等”当成“节点相等”。
比如两个链表里都有一个 8,这不代表它们相交。真正的相交,是后面那一截链表共用了同一批节点。换句话说,判断的不是 node.val,而是两个指针是不是指向同一个对象。
这地方我一般先画两条链表:
A: 4 -> 1 -> 8 -> 4 -> 5
↑
B: 6 -> 1 ┘
从 8 开始,后面的 8 -> 4 -> 5 是同一段节点,不是长得一样的两段。
最笨的写法也能做:把 A 链表所有节点丢进一个集合,再扫 B 链表,扫到第一个已经出现过的节点,就说明相交了。
代码大概这样:
deffind_join_by_seen(head_a, head_b):
seen = set()
cur = head_a
while cur:
seen.add(cur)
cur = cur.next
cur = head_b
while cur:
if cur in seen:
return cur
cur = cur.next
returnNone
这写法没毛病,排查线上链路时我也愿意这么写,直观,不容易错。缺点也明显,多用了一个集合,空间复杂度是 O(n)。
面试题一般不想让你这么轻松过,它多半会追问:不用额外空间行不行?
可以。
这个题的关键不是“谁先走到交点”,而是让两个指针走过的总路程一样。
假设 A 链表长一点,B 链表短一点。两个指针同时走,A 走到头以后切到 B,B 走到头以后切到 A。这样一来,它们都走了 A长度 + B长度。如果有交点,第二轮一定会在交点撞上;如果没有交点,最后都会变成 None。
这块别想太玄,代码反而很短:
classListNode:
def__init__(self, val=0):
self.val = val
self.next = None
defget_intersection_node(head_a, head_b):
if head_a isNoneor head_b isNone:
returnNone
p = head_a
q = head_b
while p isnot q:
p = p.next if p else head_b
q = q.next if q else head_a
return p
注意这里我用的是:
while p isnot q:
不是:
while p.val != q.val:
这个差别很要命。
is 判断的是不是同一个节点对象,val 只能说明值一样。链表题里,只要题目说“相交”,十有八九判断的都是节点引用。
再看两个边界情况。
一个是根本不相交:
A: 1 -> 2 -> 3
B: 4 -> 5
两个指针来回切一次以后,最后都会走到 None,循环停掉,返回 None。
另一个是一上来就相交:
A: 7 -> 9
B: 7 -> 9
如果 head_a 和 head_b 本来就是同一个节点,第一次判断 p is q 就成立,直接返回头节点。
这题我不建议上来就背公式。先记住一句话:两个人各走一遍对方的路,路程就被抹平了。
长链表多出来的那一截,会在切换链表后被短链表指针补回来。等长度差被抵消以后,如果后面真共用一段节点,它们自然会碰到。
这题代码短,但坑不小。尤其是 Python 里,== 可能被类重写,写链表引用判断时,我更愿意用 is。这不是洁癖,是少给自己埋一个看不见的雷。