反转单链表

148 阅读2分钟

题目描述

leetcode第206题

反转一个单链表。

示例

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

题解

思路

改变链表的next指针的指向,直接将链表反转

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null

然后就要开始反转了,首先要把 cur.next 节点用temp指针保存一下,因为接下来要改变 cur.next 的指向了,改变指向后cur向前移动时就需要temp。将cur.next 指向pre ,此时已经反转了第一个节点了。

接下来,就是循环走如下代码逻辑了,继续移动precur指针。

最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。此时我们return pre就可以了,pre指针就指向了新的头结点。

解法一(双指针法)

时间复杂度 O(n),空间复杂度 O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode temp;
        while (cur != null) { // 判定条件
            temp = cur.next; // 暂存cur向后移动的节点
            cur.next = pre; // 反转
            pre = cur; // pre向前移动
            cur = temp; // cur向前移动
        }
        return pre;
    }
}

解法二(递归)

时间复杂度 O(n),空间复杂度 O(n)

/**
 * 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 || head.next == null) {
            return head;
        }
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }
}

/*
按照递归,当执行reverseList(5)的时候返回了5这个节点,reverseList(4)中的p就是5这个节点,我们看看reverseList(4)接下来执行完之后,5->next = 4, 4->next = null。这时候返回了p这个节点,也就是链表5->4->null,接下来执行reverseList(3),代码解析为4->next = 3,3->next = null,这个时候p就变成了,5->4->3->null, reverseList(2), reverseList(1)依次类推,p就是:5->4->3->2->1->null

reverseList: head=1
    reverseList: head=2
	    reverseList: head=3
		    reverseList:head=4
			    reverseList:head=5 
					终止返回
				cur = 5
				4.next.next->4,即5->4
			cur=5
			3.next.next->3,即4->3
		cur = 5
		2.next.next->2,即3->2
	cur = 5
	1.next.next->1,即2->1
	
	最后返回cur

*/

递归二

class Solution {
    public ListNode reverseList(ListNode head) {
        // 与双指针初始化一样
        // ListNode pre = null;
        // ListNode cur = head;
        return reverse(null, head);
    }
    
    public ListNode reverse(ListNode pre, ListNode cur) { // 不断地将 cur 指向 pre
        if (cur == null) return pre;
        
        ListNode temp = cur.next; // 新的cur
        cur.next = pre;
        return reverse(cur, temp); // cur就是新的pre
    }
}