单向链表的相关算法
1.基本操作
①查找
②插入
③删除(两种)
2. 相关算法
(1)链表中的环问题
很多算法都涉及到了链表的环问题,不得不说这些问题很有意思
- 判断是否有环
这个问题就是通过两个指针,一快一慢,同时从根节点出发,如果最后能相遇,那么说明有环
- 求环的长度
这个问题也是通过两个快慢指针解决的,只不过快指针的速度要是慢指针的两倍。因为当快指针与慢指针相遇时,快指针是一定比慢指针多走了一个环的长度!而快指针走过的长度又是慢指针的两倍,所以我们就可以得到慢指针走过的长度就是环的长度
- 求环的开始节点
根据之前的环的长度问题的思考,我们很容易就可以解决环的开始节点这个问题。联想到之前我们曾经解决的链表的倒数第k个节点问题,这里我们已经可以求出环的长度,那么环的开始节点问题不就变成了求链表的倒数第k个节点问题吗?只不过这里的k变成了环的长度
(2)链表中某个位置的结点
可能是倒数第k个,也可能是中间节点
- 倒数第k个节点
链表的长度不遍历一遍是未知的,这个问题乍一看是需要知道倒数第一个然后回溯的,这样可能会遍历两遍链表或者需要内存记录。但是我们完全可以利用两个指针,利用两个指针的相对位置来解决这个问题。我们可以让一个指针先走k步,然后两个同时走,此时第一个和第二个之间是相差k步的,然后当快指针走到链表末尾后,慢指针所指的就是和它相差k步的倒数第k个节点
- 中间节点(如果链表长度为偶数则选择右边那个)
中间节点的意思就是:倒数第一半长度的结点。但是如果先获得长度,然后利用倒数第k个节点的做法,需要两次遍历。一次遍历其实就可以,因为这里需要的结点的位置很特殊:中间,如果我们还是使用快慢节点的办法的话,如何能保证快节点到达末尾时,慢节点是中间位置呢?快节点速度是慢节点的两倍,快节点一次走两步,慢节点一次走一步,当快节点到达链表尾时,慢节点的位置就是中间节点的位置。
(3)链表的顺序倒置
可能仅仅让你倒着输出,但原链表不动,也可能是让你把原来的链表倒置
- 链表倒着输出
两种,一种递归,一种使用栈。
- 反转链表
反转一个链表,最原始的想法肯定是保存好每个结点,然后倒着建立新链表。我们的思路总是想着,因为倒数第一个要成为第一个,所以我们要先搞到倒数第一个结点。这种分解子问题的方法不是最好的,最好的分解这个问题的想法应该是:要翻转整个链表,完全可以在翻转好前n-1个节点后,再把第n个节点插入到head。可以看出分解子问题的方式不同,结果也不同。
(4)两个链表
两个链表有什么问题呢?两个链表的公共节点,两个排序链表合并为一个链表
- 两个排序链表的合并
其实就和归并排序的merge过程差不多了,你可以新建一个链表, 然后把每一次头结点的较小者加入这个链表,也可以把链表1作为主链表,把链表2每个元素插入到链表1
- 两个链表的第一个公共节点
这个问题的解法就是利用之前的找倒数第k个节点的思想,可以先求出两个链表的长度,然后让长链表指针先走两个链表的长度差的步数,然后两个指针一起走,第一次相等就是公共节点。所以我们可以尽可能的用较小的复杂度先求出一些我们可以用的条件,然后利用这些条件更好的解决问题。