206. 反转链表--初级算法

链接:206. 反转链表 - 力扣(LeetCode)

题目描述

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

示例 1:

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

思路描述

方法一 双指针

        采用两个指针一前一后,前面的指针用于遍历下一结点,后面的指针用于保存新链表的头节点位置,合理利用现有指针head暂存下一节点位置,然后将新结点指向新链表头结点完成链接,更新头结点和下一结点的指针。依次遍历直到末尾,在插入最后一个节点前head正好指向空结点,插入完成后前面的指针也指向空,跳出循环,返回翻转后的链表。

代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //特殊情况,空链表和单元素链表,直接返回
        if(head==nullptr||head->next==nullptr){
            return head;
        }
        //用于访问原链表
        ListNode* p=head->next;
        ListNode* q=head;    //新链表头节点
        
        while(p){
           head->next=p->next;    //暂时保存新节点的下一节点
           p->next=q;    //新节点指向新链表头节点
           q=p;    //头节点更新
           p=head->next;    //更新移动指针,继续遍历
        }
   
        return q;
    }
};

方法二 栈思想

        栈的特点就是后进先出么,利用这一特点先将所有结点入栈,再逐个出栈,链接成新链表即为翻转后的链表。注意在入栈结束后判空操作,减少浪费时间空间。

代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        std::stack<ListNode*> st;    //定义栈,ListNode类型
        //将所有元素入栈
        while (head) {
            st.push(head);
            head = head->next;
        }
        //栈为空说明原链表为空,直接返回
        if (st.empty()) {
            return nullptr;
        }
        ListNode* L = st.top();//获取栈顶元素
        st.pop();//出栈
        ListNode* p = L;    //移动指针
        while (!st.empty()) {
            //暂存新节点
            ListNode* temp = st.top();
            st.pop();//出栈
            p->next = temp;//链接新节点
            p = p->next;//指针后移
        }
        p->next = nullptr;//最后一个节点的下一指针设为空
        return L;
    }
};

方法三 递归

        递归要找到递归中止条件,在本题中就是空链表或者只有一个元素则返回。下一步递归调用就是从当前结点的下一结点开始递归,再下一步逻辑处理,将当前结点挂到递归返回的结点的末尾,最终返回反转后的链表。

代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //递归出口条件
        if(head==nullptr||head->next==nullptr){
            return head;
        }

        //保存当前节点的下一个结点
        ListNode* n = head->next;

        //递归得到翻转后的链表,翻转后n为链表reverse的尾节点
        ListNode* reverse =reverseList(n);

        //把当前节点head,挂在尾节点n的后面
        n->next=head;

        //head成为新的尾节点,后面设为空
        head->next=nullptr;
        
        return reverse;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值