题目链接

牛客网

题目描述

输入一个链表,反转链表后,输出新链表的表头。

  1. 输入:
  2. {1,2,3}
  3. 输出:
  4. {3,2,1}

解题思路

递归

使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 ret .
此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
同时让当前结点的 next 指针指向 NULL ,从而实现从链表尾部开始的局部反转
当递归函数全部出栈后,链表反转完成。

24. 反转链表 - 图1

  1. /*
  2. struct ListNode {
  3. int val;
  4. struct ListNode *next;
  5. ListNode(int x) :
  6. val(x), next(NULL) {
  7. }
  8. };*/
  9. class Solution {
  10. public:
  11. ListNode* ReverseList(ListNode* pHead) {
  12. // 递归结束条件
  13. if(pHead==nullptr||pHead->next==nullptr)
  14. return pHead;
  15. // 递归获取后n-1个反转,返回反转后的头结点
  16. ListNode* ret = ReverseList(pHead->next);
  17. // 当前头结点的下一个结点指向当前头结点
  18. // eg: 1->2->NULL ==> NULL<-1<-2
  19. pHead->next->next = pHead;
  20. // 当前头结点指向NULL
  21. pHead->next = NULL;
  22. return ret;
  23. }
  24. };
  • 时间复杂度 O(N) : 遍历链表使用线性大小时间。
  • 空间复杂度 O(N): 遍历链表的递归深度达到 N ,系统使用 O(N) 大小额外空间。

    迭代

使用头插法。

  1. /*
  2. struct ListNode {
  3. int val;
  4. struct ListNode *next;
  5. ListNode(int x) :
  6. val(x), next(NULL) {
  7. }
  8. };*/
  9. class Solution {
  10. public:
  11. ListNode* ReverseList(ListNode* pHead) {
  12. if(pHead==nullptr||pHead->next==nullptr)
  13. return pHead;
  14. ListNode* ret = new ListNode(-1);
  15. while(pHead){
  16. // 保存下一个结点
  17. ListNode* tmp = pHead->next;
  18. // 将当前结点用头插法插入ret
  19. pHead->next = ret->next;
  20. ret->next = pHead;
  21. // 移到下一个结点
  22. pHead = tmp;
  23. }
  24. return ret->next;
  25. }
  26. };
  • 时间复杂度 O(N)
  • 空间复杂度 O(N)

双指针(一)

  • 定义两个指针: pre 和 cur ;pre 在前 cur 在后。
  • 每次让 pre 的 next 指向 cur ,实现一次局部反转
  • 局部反转完成之后, pre 和 cur 同时往前移动一个位置
  • 循环上述过程,直至 pre 到达链表尾部

24. 反转链表 - 图2

  1. /*
  2. struct ListNode {
  3. int val;
  4. struct ListNode *next;
  5. ListNode(int x) :
  6. val(x), next(NULL) {
  7. }
  8. };*/
  9. class Solution {
  10. public:
  11. ListNode* ReverseList(ListNode* pHead) {
  12. if(pHead==nullptr||pHead->next==nullptr)
  13. return pHead;
  14. ListNode *cur =NULL,*pre = pHead,*tmp = NULL;
  15. while(pre){
  16. tmp = pre->next;
  17. pre->next = cur;
  18. cur = pre;
  19. pre = tmp;
  20. }
  21. return cur;
  22. }
  23. };

双指针(二)

24. 反转链表 - 图3

  1. /*
  2. struct ListNode {
  3. int val;
  4. struct ListNode *next;
  5. ListNode(int x) :
  6. val(x), next(NULL) {
  7. }
  8. };*/
  9. class Solution {
  10. public:
  11. ListNode* ReverseList(ListNode* pHead) {
  12. if(pHead==nullptr||pHead->next==nullptr)
  13. return pHead;
  14. ListNode *cur =pHead,*tmp;
  15. while(pHead->next!=NULL){
  16. // 记录下次head指向
  17. tmp = pHead->next->next;
  18. // 当前cur转变指向
  19. pHead->next->next = cur;
  20. // 向前移动cur
  21. cur = pHead->next;
  22. // head指向cur下一个
  23. pHead->next = tmp;
  24. }
  25. return cur;
  26. }
  27. };