力扣-206-反转链表/剑指Offer-24
对于单链表而言,链表的反转需要把节点原本指向下一个节点的指向上一个节点,但是:
- 对于任意一个节点而言,它只知道自己的下一个节点而不知道上一个节点
意味着我们需要知道当前节点的上一个节点是谁?
- 递归:不考虑操作当前节点,操作当前节点的下一个节点,下一个节点上一个节点很明确,就是当前节点
- 迭代:用pre指针保存上一个节点
- 如果修改了节点的next指针(指向上一节点),那么就没法继续向下遍历下一个节点
意味着修改指针前我们要想办法保存下一个节点的信息
- 通过递归实现了从后往前改,间接通过递归栈保存了遍历路径
- 迭代:通过nxt指针保存下一个节点
递归
递归是如何解决这两个问题的?
- 它向下递归,通过压栈使得倒数第二个节点最先被访问(但是实际处理的是下一个节点,即是最后一个节点)
- 它修改的是当前节点的下一个节点,下一个节点的前一个节点我们是知道的,就是当前节点,而当前节点的下一个节点(本应指向前一个节点,但是我们不知道)被置空了
但是这里的置空除了一种情况下,都是没有意义的,因为它会被下一次操作覆盖,没必要特意置空
这中特殊情况就是最后一个,或者说原本的头节点,不会还有操作了,所以必须手动把它的下一个节点指针置空,这就是其他节点都多出了一步的原因
class Solution { public: ListNode* reverseList(ListNode* head) { // 递归的写法其实是相当于从后往前操作 // 每次先向下递归一层,从倒数第2个节点开始操作 // 但也不是操作倒数第二个节点,而是操作它的后一个节点 // 因为不知道当前节点的前一个节点,但是知道后一个节点的前一个节点,就是当前节点 // 每一步都把后一个节点的指针反转 if(!head||!head->next) return head; ListNode* reversedHead = reverseList(head->next);// 最后一层返回的是最后一个节点,即是新的头节点 head->next->next= head;// 反转下一个节点 head->next=nullptr;// 其实这一句只有在处理最后一个就也就是原本的头节点有效,其余时候都是不必要的 // 只有头节点反转后指向空节点 return reversedHead;// 这个节点在整个递归过程中没有改变 } };
递归中head指针只改变了next指针的指向,本身没有改变
迭代
迭代又是怎么解决这个问题的?
它用了三个指针
- pre用于保存前一个节点,用于反转指针指向
- cur用于指向当前节点,用于遍历链表
但其实不考虑不修改head的话,其实两个指针就够了
但这样做的话其实是修改了head指针的,如果其他地方要用到head指针的原始值,就不能这么干
- next保存下一个节点
// 递归用到的三指针 ListNode* reverseList(ListNode* head) { // 定义了两个指针 ListNode* pre = nullptr;// 用于保存前一个指针 // 其实两个节点也行,但是head指针会被修改,最后会是一个nullptr // ListNode* cur = head;// 当前节点指针,用于遍历 while (cur) { ListNode* nxt = cur->next;// 初始化写到里面来,cur->next可能是空指针 cur->next = pre;// 反转当前指针的指向 // 移动两个指针 pre = cur; cur = nxt; } return pre;// 为什么是pre?cur最后的指向会是空指针 }
这里也很巧妙的解决了输入指针为空,以及链表长度为1的情况
剑指Offer里定义了一个看起来不必要的reversedHead
指针用于返回结果,另外,也多了一句无用的判断if(!nxt) reversedHead = head;
,可以改写成这样,if(!nxt) return head;
,但还是无用
如果这个判断存在,那么这个判断一定会比while
中的条件判断先一步出结果,while
的条件反而显得多余了,然后由不满足返回值规则
反而,如果去掉,并没有什么影响,用pre
指针返回更巧妙,它最终会被更新为指向最后一个节点,也就是反转后的第一个节点
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/16193916.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步