面试题24:反转单链表(解法二:递归法)

反转单链表的两种方法

今天看了帅地的第二版资料,突然发现单链表的反转居然还可以用递归来做,太妙了吧!

  直接上代码,目前只有C++版的(用指针写链表它不香吗?):

// 递归法反转单链表
ListNode* reverseListPlus(ListNode* pHead){
    if(pHead == nullptr || pHead->next == nullptr)
        return pHead;

    ListNode* reverseNode = reverseListPlus(pHead->next);
    pHead->next->next = pHead;
    pHead->next = nullptr;

    return reverseNode;
}

int main()
{
    ListNode* pNode1 = createListNode(1);
    ListNode* pNode2 = createListNode(2);
    ListNode* pNode3 = createListNode(3);
    ListNode* pNode4 = createListNode(4);
    ListNode* pNode5 = createListNode(5);

    connectListNodes(pNode1, pNode2);
    connectListNodes(pNode2, pNode3);
    connectListNodes(pNode3, pNode4);
    connectListNodes(pNode4, pNode5);

    PrintListNodes(pNode1);
    // 递归法反转链表
    reverseListPlus(reverseList(pNode1));

    // 测试反转是否成功
    PrintListNodes(pNode5);
    return 0;
}

  代码解释:

  1、ListNode* reverseNode = reverseListPlus(pHead->next);

  • 递归法的目的是要返回一个新的头节点,这个新的头节点是原来链表的尾节点。

  • 递归是方法自己调用自己,栈的特性是先进后出、后进先出。所以这段代码的作用是不断的去压栈。

  2、pHead->next->next = pHead;把当前节点指向的下一个节点的指向变为自己。(不要慌,这段代码的解释,下面有图有真相);

  3、pHead->next = nullptr; 当前节点指向的下一个节点变为空。

  是不是看了上面的解释还有点不理解,别急,我第一次看这段代码的时候也是懵逼的(内心wc:这写了个啥,怎么就反转链表了),要理解这段代码首先,我们得去压几个栈:

  ListNode* reverseNode = reverseListPlus(pHead->next);这段代码会执行四次,压栈四次,如图:


  if(pHead == nullptr || pHead->next == nullptr) return pHead;这段代码会让 reverseListPlus(pHead(4)) 发生弹栈,然而链表没有发生任何变化。。。方法继续执行。


  接着 reverseRecursion(head(3)) 弹栈执行下面这段代码
  head.next.next = head;
  head.next = null;
  reverseRecursion(head(3)) 执行之后链表发生了如下变化:


  持续到最后reverseRecursion(head(1))出栈:链表反转完成,撒花
  head.next.next = head;
  head.next = null;

posted @ 2020-08-17 12:54  程序员曾奈斯  阅读(188)  评论(0)    收藏  举报