一、题目描述:
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
二、思路分析:
这题非常高频。如果面试的时候遇到做不出来好像很丢人的样子。。。
看题中提示,这题一般有两种解法,递归和迭代。所谓递归和迭代的在翻转数组时变换的差别在于,是从head开始翻转,还是从tail开始翻转。
先说递归,这是从后向前的翻转,先变换尾结点的next,再逐步向前。如果照这个思路去想就很简单了。
- 想要翻转链表,是不是把当前结点后面的结点指向当前结点就可以了?
- 怎么获取后面的结点?注意,这里是后面结点翻转后的状态,直接递归调用
reverseList(head.next),然后通过head.next获取 - 让
head.next指向自己 - 然后
head指向null
这里为什么head会指向空?因为用递归的方式是从后向前的,当前结点head应该指向前驱结点的,但是在当前的递归嵌套中还处理不了前驱结点,所有要指向null
再说迭代法。相比较递归,这种翻转是从前向后的,不过要注意的是一次迭代只处理一个指向的翻转,不要想太多,只处理一个,让当前结点指向前驱就可以了,然后同时将当前结点和前驱向后滚动。具体步骤看代码。
三、AC 代码:
class Solution {
fun reverseList(head: ListNode?): ListNode? {
return solution2(head)
}
// 迭代
fun solution2(head: ListNode?): ListNode? {
var prev: ListNode? = null
var current: ListNode? = head
while (current != null) {
var next = current.next
current.next = prev
prev = current
current = next
}
return prev
}
// 递归
fun solution1(head: ListNode?): ListNode? {
if (head?.next == null) {
return head
}
var p = solution1(head.next)
head?.next?.next = head
head.next = null
return p
}
}
四、总结:
之前做过的题,现在再拿过来做还是会忘记,希望能多做几遍真正掌握链表操作
本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情