今天,我们来聊单链表的就地反转,这也是一个高频笔试面试题目,能检验面试者的基本功底。
所谓就地,意思就是要求空间复杂度为O(1). 这个题目很简单吗?未必!
当年,在腾讯的校招面试中,我遇到了这个问题,记得当时写得并不好,加上面试官一再追问,我慌了,结果很尴尬。
去年,在松山湖的一个饭局上,和业界Android某大佬聊天,他说自己去字节跳动面试,被要求写单链表的就地反转,没有写对。
他可是写了好几本Android核心书籍啊,居然被这个问题给卡住了,确实大大出乎我的意料。
这让我想起了一件趣事:Homebrew 是 Mac OS X 上的著名软件,其作者Max Howell去Google面试,遇到二叉树的反转题目,没有做出来,被Google拒录。
要知道Google的很多工程师,都要使用Max Howell写的Homebrew软件啊。后来,Max Howell在 Twitter上吐槽说:
哈哈,就是这么有趣。不过,今天我们不说反转二叉树,而说反转链表。就地反转链表,真有这么难吗?显然不是。
这里的关键就是,把图画好,把逻辑缕清,代码就会一气呵成,也就几行而已。接下来,我们看看单链表就地反转的逻辑图:
其中:p负责遍历,q负责尾随,r负责维护反转后的结果。每次把q结点摘下来,倒插到r链表中。
代码实现如下:
func reverseList(head *ListNode) *ListNode {
p := head
q := p
r := q
r = nil
for p != nil {
q := p
p = p.Next
q.Next = r
r = q
}
return r
}
在leetcode上进行了测试,验证通过。可以看到,确实是几行代码就能搞定问题。
具体过程是:使用p进行遍历,然后q紧跟p的步伐,并记录摘下来的结点,然后使用r进行管理,保存最终的反转链表。
单链表的就地反转,虽然简单,但在面试特定的场景和压力下,要现场写正确,也不太容易。所以,还是要镇定啊,面试之前要多多练习手写代码。
最后,希望大家在面试刷题中,找到快乐,获得进步。祝找工作的朋友一切顺利,拿到心仪的offer, 钱多多,福利多多。