算法~链表反转

86 阅读2分钟

描述:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 

  • 示例1 : image.png

输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]

  • 示例 2: 输入:head = [1,2] 输出:[2,1]

  • 示例 3: 输入:head = [] 输出:[]

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re…

解法1:双指针迭代法

  • 解题思路:

    • 采用前后双指针遍历,一个当前指针一个前指针,前指针初始为null,当前指针初始指向头节点head
    • 遍历过程中,定义一个临时节点存储next节点,当前指针cur的next指向前指针pre,pre前进一位置为cur,cur前进一位置为刚刚临时保存的next节点
  • 复杂度:时间复杂度:O(n) 空间复杂度:O(1)

  • 动画展示: image.png

  • Java实现:

/**
 * 双指针迭代法将链表反转 [时间复杂度:O(n) 空间复杂度:O(1)]
 *
 * @param head 链表(头节点)
 * @return 反转后的新链表
 */
public static ListNode reverseList(ListNode head) {
    ListNode pre = null;
    // 当前节点
    ListNode cur = head;
    while (cur != null) {
        // 记录当前节点的下一个节点
        ListNode next = cur.next;
        // 然后将当前节点指向pre
        cur.next = pre;
        // pre和cur节点都前进一位
        pre = cur;
        cur = next;
    }
    return pre;
}

解法2:递归法

  • 解题思路:

    • 递归的两个条件
      1. 终止条件是当前节点或者下一个节点为null
      2. 在函数内部,改变节点的指向,head的下一个节点指向head递归函数那句 head.next.next = head
  • 复杂度:时间复杂度:O(n) 空间复杂度:O(n)

  • 动画展示: image.png

  • Java实现:

/**
 * 递归法将链表反转 [时间复杂度:O(n) 空间复杂度:O(n)]
 *
 * @param head 链表
 * @return 反转后的新链表
 */
public static ListNode reverseList2(ListNode head) {
    // 递归终止条件是当前为空,或者下一个节点为空
    if (head == null || head.next == null) {
        return head;
    } else {
        // 这里的cur就是最后一个节点
        ListNode cur = reverseList2(head.next);
        // 如果链表是 1->2->3->4->5,那么此时的cur就是5
        // 而head是4,head的下一个是5,下下一个是空
        // 所以head.next.next 就是5->4
        head.next.next = head;
        // 防止链表循环,需要将head.next设置为空
        head.next = null;
        return cur;
    }
}