剑指 Offer 24. 反转链表

题目链接:https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof

本文给出两种语言的解法:1.JavaScript 递归解法、迭代解法)  2.Java(迭代解法)

 

一、JavaScript(递归解法、迭代解法

1.递归解法

 1 /**
 2  * 先处理链头为空的情况(链为空)
 3  */
 4 var reverseList = function(head) {
 5   if(head == null) return head;
 6 }
 7 /**
 8  * 第一步就是划分小问题:需要将当前结点的下一个结点指向当前结点; ...(1)
 9  *    也就是head.next.next = head; ...(1)
10  * 但在操作(1)之前,必须解决下一个结点的小问题(也就是要对下一个结点进行操作1)
11  * 而解决小问题的方法就是reverseList(head)
12  * 因此:
13  */
14 var reverseList = function(head) {
15   if(head == null) return head;
16   reverseList(head.next);
17   head.next.next = head; //...(1)
18 }
19 /**
20  * 第二步就是找递归出口:到什么时候就没有了下一个结点的小问题?
21  * 当下一个结点为空时:head.next == null
22  * 注意:当到了递归出口(下一个结点为空)时,所传入的结点将会是新的头节点。
23  */
24  var reverseList = function(head) {
25   if(head == null || head.next == null) return head;
26   reverseList(head.next);
27   head.next.next = head; //...(1)
28 }
29 /**
30  * 因为题目要求返回链表反转后的新头结点,
31  * 那么需要将新头结点层层传递出去:保留递归出口返回的新头结点逐层返回
32  */
33  var reverseList = function(head) {
34   if(head == null || head.next == null) return head;
35   let newHead = reverseList(head.next);
36   head.next.next = head; //...(1)
37   return newHead;
38 }
39 /**
40  * 到此,除了旧头结点之外的结点的next都已经完成重新指向。
41  * 根据题目要求,旧头结点将指向null;
42  * 在代码中对每个结点都进行next赋值null操作:head.next = null;
43  * 虽然对每个结点都进行了该操作(本不需要的操作),
44  * 但除了旧头结点外的结点的next都将会重新指向(在递归的外层会重新指向)。
45  */
46  var reverseList = function(head) {
47   if(head == null || head.next == null) return head;
48   let newHead = reverseList(head.next);
49   head.next.next = head; //...(1)
50   head.next = null;
51   return newHead;
52 }

 

2.迭代解法

由头结点始,逐个访问结点并对其操作:将其next指向前一个结点(在此操作前需保留下一个结点的引用),

在该操作有一个问题就是在访问当前结点时,如何指向前一个结点?解决手段就是在访问第二个结点之前先保存第一个结点(也就是在遍历下一个结点之前保存当前结点的引用)。

 1 /**
 2  * @param {ListNode} head
 3  * @return {ListNode}
 4  */
 5 var reverseList = function(head) {
 6     let tem1 = null;
 7     let tem2 = null;
 8     let index = head;
 9     while(index !== null) {
10         tem2 = index.next;
11         index.next = tem1;
12         tem1 = index;
13         index = tem2;
14     }
15     return tem1;
16 };

 

二、Java(迭代解法)

 1 /**
 2  *  @author 不乏理想的三师弟
 3  *  解法一 也就是题解中的迭代解法
 4  *  原理:
 5  *  由头结点开始,遍历链表;同时完成两件事:
 6  *  1、将当前结点的next指向前一个结点;
 7  *  2、并且对下一个结点也能做第一件事;
 8  *  
 9  *  用head代表当前结点,
10  *  要做的第一件事:head.next 指向前一个结点;
11  *  因此要有临时变量pre保存前一个结点;(初始时pre当然为null)
12  *  
13  *  (1)head.next = pre; // 将当前结点的next指向前一个结点;
14  *  
15  *  当执行语句(1)时,下一个结点的引用会被抹去;
16  *  因此在执行语句(1)之前,要另一个临时变量tem保存下一个结点:tem = head.next;
17  *  执行完语句(1)后,就准备操作下一个结点;
18  *  
19  *  (2)head = tem; // 准备操作下一个结点
20  *  
21  *  在执行语句(2)时,原本head的结点就会被抹去;
22  *  因此在执行语句(2)之前,要将head结点赋值给pre:pre = head;
23  *  
24  *  语句顺序如下:
25  *  head.next = pre; (1)
26  *  tem = head.next;
27  *  pre = head;
28  *  head = tem; (2)
29  */
30 public static ListNode reverseList(ListNode head) {
31     if(head == null) return null;
32     ListNode pre = null, tem = null;
33     
34     // 为了不打乱语句的逻辑顺序就用break来跳出循环
35     while (true) {
36         tem = head.next;
37         head.next = pre; 
38         if (tem == null) {
39             // beak要在head.next = pre后执行;
40             // 因为在最后一刻还要将当前结点的next指向前一个结点
41             break; 
42         }
43         pre = head;
44         head = tem;
45     }
46     return head;
47 }

 

posted @ 2021-08-12 21:58  不乏理想的三师弟  阅读(31)  评论(0)    收藏  举报