被裁后的第3个月,面试官问我空窗期在干嘛。 我说:"跑外卖。"他愣住了。我接着说:"送了1278单,超时率0.3%,差评0条
刚看到个贴子,说有网友被裁第3个月去面试,问空窗期干嘛,他很老实说去送外卖,然后现场气氛突然安静了。
我觉得这事吧,最扎心的不是送外卖,而是“体面”这俩字。很多人嘴上说职业不分贵贱,真轮到自己或者员工去跑外卖,心里那道坎一下就出来了。
可换个角度想,失业了不躺平,顶着压力出去跑单,每天风里来雨里去,这执行力、抗压能力、时间管理,哪样不是职场刚需?
我倒觉得,送外卖完全可以讲,但话术要升级一下:把“跑外卖”讲成“为了维持收入选择高强度的服务类工作,同时复盘职业规划”,再顺手亮个数据,效果就不一样了。
算法题:两数相加
昨天晚上十一点多,我在公司楼下等外卖,手机快没电,人也快没电,小李突然在群里丢过来一句: “东哥,那个两数相加的链表题,你是怎么写的?我老写成大数加法用 int,直接爆了……”
我当时整个人懵了一下,又好气又好笑,这题你们是不是面试被问烂了那个。
比如 342 + 965,你肯定是这么算的: 2 + 5 = 7,记 7; 4 + 6 = 10,写 0 进 1; 3 + 9 + 1(进位) = 13,写 3 再进 1,最后得到 1307。
注意一个细节,你是从个位开始往前算的,不是从最高位。这题其实就完全是把这个动作,搬到链表上去。
面试题里的规则大概是这样: 两个非空链表,每个节点存一位数,低位在前,高位在后。 比如数字 342 存成:2 -> 4 -> 3965 就是:5 -> 6 -> 9然后要你返回一个新的链表,表示它们的和,也是低位在前那种。
小李原来的写法是,直接把俩数从链表里读出来,拼成字符串,再转成 int 去相加,我就问他:
“你想象一下,面试官给你俩 1000 位的小数,你一个 int 顶得住?long long 也不行啊兄弟。”
所以这个题的关键其实就一句话:别把它当“数字加法”,就当“链表逐位相加”。每一位自己算,顺手带上一个进位变量,和你纸上算是一个套路。
脑子里先有个画面: 你一只手指着链表 l1 的当前节点,一只手指着 l2 的当前节点,兜里揣着一个 carry(进位),默认是 0。
每一步就干三件小事:
把两个节点的值拿出来,没有节点就按 0 算。 sum = x + y + carry当前位是 sum % 10,新的进位是sum // 10
然后指针往后挪。一直走到两个链表都空了,还要看看 carry 里是不是还有 1,要的话再补一个节点。就这么碎碎念地一直加下去。
我一般会先写个最小的链表节点定义,Python 里就这样:
classListNode:
def__init__(self, val=0, next=None):
self.val = val
self.next = next
然后是核心的加法函数,这个才是面试官盯着看的地方:
defaddTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode:
# 哨兵节点,方便返回结果
dummy = ListNode(0)
cur = dummy
carry = 0# 进位,开始是0
# 只要还有一个链表没走完,或者还有进位,就继续算
while l1 isnotNoneor l2 isnotNoneor carry != 0:
x = l1.val if l1 isnotNoneelse0
y = l2.val if l2 isnotNoneelse0
s = x + y + carry
carry = s // 10
digit = s % 10
# 当前位的结果挂到新链表后面
cur.next = ListNode(digit)
cur = cur.next
# 往后挪动指针
if l1 isnotNone:
l1 = l1.next
if l2 isnotNone:
l2 = l2.next
return dummy.next
这个写法的几个小点,面试的时候容易被问:
为啥要用
dummy这个哨兵节点? 因为你一开始还不知道结果链表的头在哪,直接造一个“假的头”,后面都往它后面接,最后dummy.next就是真头。这样就不用写“如果是第一个节点就怎么怎么”的那些 if,代码干净很多。while里为啥要把carry != 0也算进去? 就是为了解决这种情况: 5 -> None 5 -> None 5 + 5 = 10,结果得是0 -> 1,如果你只看链表是否为空,进位 1 就丢了。时间、空间复杂度怎么说? 别紧张,张嘴就一句: “每个节点只访问一次,所以时间复杂度 O(n),n 是两个链表的最长长度;额外空间就是结果链表本身,算题目要求的,额外辅助空间是 O(1)。” 面试官一般就点点头过去了。
再顺手提醒几个常见“迷之翻车点”,我看好几个新人都栽过:
一个是不同长度的情况,比如:9 -> 9 -> 91你不能假设两个链表一样长,所以取值的时候一定要写成 x = l1.val if l1 else 0 这种,不然直接空指针见祖宗。
还有一个是原地修改 vs 新建链表。 有的人喜欢在 l1 上直接改,这个思路也行,但是面试题一般默认你别动入参,新建一个结果链表最保险,不容易搞出一些看不见的副作用,特别是后面还有别的逻辑复用这个链表的时候。