最近在刷关于链表的题目,特开一贴记录有意思的相关题目。
介绍
尾插法“新建”链表的思路可以解决绝大多数链表题目。
链表题目:第一反应就应该是头节点是否被操作,要不要dummy
虚拟头节点方便操作。
尾插法“新建”链表思路:不要在原链表上进行指针操作,只需要原链表上的「满足题意」的节点“拆”下,然后拼接在新链表上。(注意:此处新建非重新malloc节点,而是修改原链表结点的指针指向。)
因此在解决链表一类问题时,如果想不到巧妙地递归方法
,就用迭代
。使用迭代
脑海里就要有“原链表”和“新链表”这两个链表,因此题意就可以转换为如何筛选出“原链表”符合题意的节点并连在“新链表”上[1]。
1. lc 82 - 删除排序链表中的重复元素 II
- 题目来源
- 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
- 难度:中等
1.1 解题思路 - 迭代
最近对递归
的做法较为熟练,但迭代
反而不熟练。这是一道用迭代完成的题目。下面是步骤。
- 与链表的其他题目类似,为了防止删除头结点的极端情况发生,先创建空结点
dummy
,使dummy
指向传入的head结点。 - 然后创建
cur
的指针,指向链表的头部(即cur = dummy
)。 - 进入while循环:接着对
cur
指针迭代,因为要对比cur(cur最初始的定义指向空结点)指针的下一个结点
与下下一个结点
的值
是否相等,为了防止产生空指针异常,故退出while
循环迭代的条件为:cur.next and cur.next.next
。此时创建一个临时指针tmp
,指向cur的下一个节点
。
- 3.1 在迭代过程中,如果
cur.next.val == cur.next.next.val
说明此时有重复元素,临时指针tmp
发挥作用:将推进链表的迭代,而cur
指针停止移动,即tmp
指向的第一个重复元素所在的位置。 - 3.1.1 通过一个内部的
while
循环去重。若tmp指针的结点
与下一个结点
的值
是相等,则直接将tmp
指向下一节点,向后迭代即可。反之,不等时,便可去重。此时tmp
指向的是重复元素中的便是最后一个位置。最后cur.next = temp.next
就实现了消除重复元素。
- 3.1.1 通过一个内部的
- 3.2 如果
cur.next.val != cur.next.next.val
说明此时cur
后面两个节点不是有重复元素,cur
向后迭代。
- 迭代完成后,返回
dummy
的next
。
1.2 时间复杂度
- 时间复杂度: O(n)。看似两层循环,其实内层循环和外层循环的迭代路径是互补的,本质上只遍历一次链表就结束。
- 空间复杂度: O(1)。
1.3 代码
1 | # Definition for singly-linked list. |
2. 剑指 Offer 35 - 复杂链表的复制
- 题目来源
- 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
- 难度:中等
2.1 解题思路 - 哈希表 + 链表
2.2 代码
1 | """ |
相关题目
更多链表题目请搜索tags
下的链表。
参考
[1] boille. 通用思路解决链表问题. https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/solution/tong-yong-si-lu-jie-jue-lian-biao-wen-ti-xaeu/
[2] keithy. JAVA “哑结点 + 非递归” 容易理解,用时1ms. https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/solution/java-ya-jie-dian-fei-di-gui-rong-yi-li-jie-yong-sh/
[3] jyd. 剑指 Offer 35. 复杂链表的复制(哈希表 / 拼接与拆分,清晰图解). https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/