链表常见面试题
-
基本题
- 反转单向链表
- 反转双向链表
- 如果存在换头的操作,函数要有返回值
- 打印两个有序链表的公共部分,有点类似merge外排的过程
-
面试方法论
- 笔试时,链表题目不用在意空间复杂度,减少时间复杂度
- 对于面试,时间复杂度第一位,一定要找到空间最省的方法(考coding)
-
重要技巧
- 容器(哈希表等)
- 快慢指针
-
判断一个链表是否是回文结构
- 笔试怎么做
- 放到栈里面就可以了,遍历链表与栈弹出的相同,有一个不一样就是回文
- 省一点空间,在栈里面只压入右半部分,遍历链表左半部分进行比较
- 快慢指针
- 如何知道当前是右半部分需要压栈
- 一个指针一次走一步,一个指针一次走两步,当快指针走完时,慢指针来到中点的位置
- 将慢指针后面部分的内容压栈
- 需要根据题目的具体情况定制,边界条件需要修改,需要写熟特定的情况,
- 一个走完,若奇数在唯一中点,若偶数,在中点的前一个
- 一个走完,若奇数再唯一中点,若偶数,再中点的后一个
- 一个走完,若奇数在唯一中点的前一个,若偶数,在中点的前一个再前一个
- 快慢指针
- 在面试中的做法:O(1)的额外空间复杂度
- 第一遍遍历,快慢指针
- 慢指针停在中点位置,将后面的单链表逆序
- 从头和慢指针所在的位置开始,同时遍历,(同时把链表的顺序恢复)取到的数都一样,则是回文
- 笔试怎么做
-
给定一个划分值,将一个单链表划分成左边小,中间相等,右边大的形式
- 笔试怎么做
- 将单链表放到一个数组(节点类型)中
- 在数组中进行partition
- 将数组中所有的节点串联起来
- 在面试中的作法
- 小于部分的头尾sh,st
- 大于部分的头尾eh,et
- 等于部分的头尾bh,bt
- 在单链表中进行partition只需要建立新的连接,不需要进行位次调换,不会影响稳定性
- 三块进行连接时要讨论清除边界,不能引用空指针的next
- 笔试怎么做
-
复制含有随机指针节点的链表,O(N)时间,O(1)额外空间
- 假设可以使用额外空间
- 直接使用哈希表map就可以完成
- 遍历链表,生成克隆节点和map
- 遍历老链表,根据map设置新链表的连接
- 不适用哈希表的方式
- 生成克隆节点,挂在老节点的紧接之后
- 则任何一个节点的next就是克隆节点
- 把random指针设置后
- 重新设置克隆节点和老节点的next,将新老链表分离
- 为什么省掉了哈希表
- 哈希表用来形成老节点和克隆节点的对应关系
- 这里克隆节点直接挂在老节点之后的特殊位置关系起了这种对应关系的作用
- 假设可以使用额外空间
-
两个单链表(可能有环也可能无环)相交的一系列问题,返回相交的第一个节点,或者返回不相交
聊个链表长度之和为N,O(N)时间,O(1)额外空间
- 首先分辨某一个链表的有环无环
- 如果有环,返回第一个入环的节点,否则返回无环
- 可以使用哈希表Set,遍历链表,每次检查是否存在,第一次存在的点就是入环节点
- 不用额外数据结构需要使用快慢指针,比较难以理解
- 快指针一旦走到空,一定无环
- 如果两个指针相遇(慢指针在环里走不会超过一圈),一定有环
- 相遇之后,快指针回到头节点,慢指针不动
- 两个指针都每次走一步,一定会在入环节点相遇
- 两个单链表都是无环的,相交的话一定是Y型,一直到空的部分一定都公有
- 遍历两个链表到各自的最后一个节点,记录两者的长度
- 判断两个尾节点的内存地址是否相同,不相同则不相交
- 如果相交,较长的哪个先走长度只差,两者再一起走,一定在第一个相交的节点相交
- 一个单链表有环,一个单链表无环
- 两个链表不可能相交
- 两个链表有环,可能不相交,入环节点相同,入环节点不相同
- 判断入环节点内存地址是否相同
- 入环节点相同转换为无环链表的相交问题
- 让一个单链表从loop1开始继续走,如果遇到loop2就是入环节点不同的情况,否则两者不相交
- 相交时返回loop1或者loop2都可以
- 判断入环节点内存地址是否相同
- 首先分辨某一个链表的有环无环