1. 题目描述

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

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

限制:

  • 0 <= 节点个数 <= 5000

    2. 解题思路

    对于链表的操作,实际上就是在操作链表的指针。所以,对于这道题,我们能想到的最直接的方法就是将每个节点的指针指向该节点的前驱节点,这样整个链表就反转过来了,我们需要设置三个指针:分别指向前驱节点,当前节点,后驱节点。

复杂度分析:

  • 时间复杂度:O(n),在反转链表时,需要遍历整个链表;
  • 空间复杂度:O(1),在遍历链表过程中,不需要额外的空间储存变量。

再尝试着使用递归来实现这个题目:

对于这道题来说,最重要的就是反转的操作:当前节点是head,那下一个节点就是head.next,我们只要将head.next指向head,就实现了反转。最后只要将headhead.next之间的指针断开,就实现了两个节点之间的指针反转。最后在递归执行以上步骤即可。

复杂度分析:

  • 时间复杂度:O(n),在反转链表时,递归的深度为n;
  • 空间复杂度:O(1),在遍历链表过程中,不需要额外的空间储存变量。

    3. 代码实现

    第一种方法:
    1. /**
    2. * Definition for singly-linked list.
    3. * function ListNode(val) {
    4. * this.val = val;
    5. * this.next = null;
    6. * }
    7. */
    8. /**
    9. * @param {ListNode} head
    10. * @return {ListNode}
    11. */
    12. var reverseList = function(head) {
    13. let pre = null
    14. let cur = head
    15. while (cur!= null){
    16. let next = cur.next
    17. cur.next = pre
    18. pre = cur
    19. cur = next
    20. }
    21. return pre
    22. };
    第二种方法:
    1. /**
    2. * Definition for singly-linked list.
    3. * function ListNode(val) {
    4. * this.val = val;
    5. * this.next = null;
    6. * }
    7. */
    8. /**
    9. * @param {ListNode} head
    10. * @return {ListNode}
    11. */
    12. var reverseList = function(head) {
    13. if(!head || !head.next){
    14. return head
    15. }
    16. let res = reverseList(head.next)
    17. head.next.next = head
    18. head.next = null
    19. return res
    20. }

    4. 提交结果

    第一种方法:
    剑指 Offer 24. 反转链表 - 图1
    第二种方法:
    剑指 Offer 24. 反转链表 - 图2