剑指offer面试题24:反转链表

这篇博客详细介绍了如何通过迭代、递归和使用栈这三种方法来反转单链表。提供了详细的代码实现,包括利用临时变量、栈以及双指针技巧来完成链表的反转操作。每种方法都清晰地展示了反转过程,有助于理解链表操作和算法思维。
摘要由CSDN通过智能技术生成

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

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

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

class Solution {
public:
    ListNode* reverseList(ListNode* head) 
    {
        vector<int> reList; //存放链表节点值的数组
        ListNode *res , *p = head;
        while(p)
        {
            //依次将链表节点顺序插入数组中
            reList.push_back(p->val);
            p = p->next;
        }
        
        // reverse(reList.begin(),reList.end());
        // res = head;
        // for(int i=0;i<reList.size();i++)
        // {
        //     res->val = reList[i];
        //     res = res->next;
        // }
        res = head;
        for(int i = reList.size()-1; i >= 0; i--)
        {
            res->val = reList[i];
            res = res->next;
        }
        return head;
    } 
};

 

class Solution {
public:
    ListNode* reverseList(ListNode* head)
    {
        //利用栈存储链表节点值
        stack<int> st;
        while(head != nullptr)
        {
            st.push(head->val);
            head = head->next;
        }
        ListNode* dummy = new ListNode(-1);
        ListNode* p = dummy;
        while (!st.empty())
        {
            p->next = new ListNode(st.top());
            if (!st.empty())
                st.pop();
            p = p->next;
        }
        return dummy->next;
    }
};

方法一:迭代

class Solution {
public:
    ListNode* reverseList(ListNode* head)
    {
        ListNode* res = nullptr;
        while (head != nullptr){
            ListNode* newHead = new ListNode(head->val);
            newHead->next = res;
            res = newHead;
            head = head->next;
        }
        return res;
    }
};


对于本题来说,采用迭代法去做,一般会都会设置三个指针。

pre:指向当前节点的前一节点,用于反转链表;

cur:指向当前节点,用于遍历整个链表;

next:指向当前节点的后(下)一节点,用于在反转前,保留 cur 的下一节点,防止反转时,链表断开,无法找到 cur 后面的节点。

class Solution {
public:
    ListNode* reverseList(ListNode* head) 
    {
        if(head == NULL || head->next == NULL)
        {
            return head;
        }
         
        ListNode *pre = nullptr,*cur = head;
        while(cur != nullptr)
        {
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;    
    }
};

方法二:递归
考虑使用递归法遍历链表,当越过尾节点后终止递归,在回溯时修改各节点的 next 引用指向。

recur(cur, pre) 递归函数
1、终止条件:当 cur 为空,则返回尾节点 pre (即反转链表的头节点);
2、递归后继节点,记录返回值(即反转链表的头节点)为 res ;
3、修改当前节点 cur 引用指向前驱节点 pre ;
4、返回反转链表的头节点 res ;
reverseList(head) 函数:
调用并返回 recur(head, null) 。传入 null 是因为反转链表后, head 节点指向 null ;

class Solution {
public:
    ListNode* reverseList(ListNode* head) 
   {
        return recur(head, nullptr);           // 调用递归并返回
    }
private:
    ListNode* recur(ListNode* cur, ListNode* pre) 
   {
        if (cur == nullptr) return pre;        // 终止条件
        ListNode* res = recur(cur->next, cur); // 递归后继节点
        cur->next = pre;                       // 修改节点引用指向
        return res;                            // 返回反转链表的头节点
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值