LeetCode系列之「反转链表」

剑指 Offer 24. 反转链表

ListNode

// Definition for singly-linked list.
public class ListNode {
     
    int val;
    ListNode next;
    ListNode(int x) {
      
      	val = x; 
    }
}

一、迭代解法

class Solution {
     
    public ListNode reverseList(ListNode head) {
     
        if(head == null) return null;
      	// 初始化指针的位置
        ListNode cur = head;  
        ListNode pre = null;
      
        while(cur != null){
        
            ListNode nxt = cur.next;  // ① 保存当前cur的下一个节点
            cur.next = pre;  // ② 改变当前节点的指针,指向前一个节点
            pre = cur;       // ③ pre和cur整体往后移,但是必须先移动pre
            cur = nxt;       // ④ 
        }
        return pre;
    }
}

迭代解法不难理解,需要注意的有两点:

  1. 不需要虚拟节点,将 pre = null 即可;
  2. ① ② ③ ④ 的顺序是固定的。

二、递归解法

class Solution {
     
    public ListNode reverseList(ListNode head) {
     
        if(head == null || head.next == null) return head;

        ListNode tmp = reverseList(head.next);
        head.next.next = head;
        head.next = null;

        return tmp;
    }
}

利用递归结题的关键,首先要明白 reverseList(ListNode head) 这个函数的作用就是:

  • 给我一个头结点,我就能把这个链表反转过来,然后返回反转后的链表的头结点。

不要去想这个函数的内部,利用递归解题都是这样,就把这个函数当做一个黑盒子,然后明白三件事:

  1. 给我这个函数,我就能实现某个功能
  2. 函数的参数是啥
  3. 函数返回的是啥

接着,我们就用这个黑盒子来反转一个链表,链表的头结点为head

Node1/head
Node2
Node3
Node4/tail
null

先不用管head,假如执行 ListNode tmp = reverseList(head.next);这么一个操作会发生什么?

  • 就会发生:以 head.next 节点(即Node2节点)为头结点的链表,后面的节点的next指针都会发生反转,最终 head.next 节点变为尾节点,
  • 如下
Node1/头节点
Node2
Node4/尾节点
Node3

此时只需执行下面两步操作:

  • head.next.next = head 将Node2的next节点指向head
  • head.next = null 将head的的next节点指向null
Node4/尾节点
Node3
Node2
Node1/头节点
null

你可能感兴趣的:(算法与数据结构,链表,指针,算法,leetcode,java)