NC78 反转链表

反转链表

题目描述

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

题目传送门

示例

输入

{1,2,3}

返回值

{3,2,1}

题解

方法一:构造新链表

如果内存要求不高,可以先将单链表的每一个指针都存下来,然后再按顺序逐个构造新的链表。

时间复杂度:O(n)

空间复杂度:O(n),使用了vector来存储

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL || pHead->next == NULL)
            return pHead;
        vector<ListNode*> vec;
        while(pHead){
            vec.push_back(pHead);
            pHead = pHead->next;
        }
        // 反转vector,也可以逆向遍历
        reverse(vec.begin(), vec.end());
        ListNode* head = vec[0];
        ListNode* cur = head;
        for(int i=0; i<vec.size(); i++){
            cur->next = vec[i];
            cur = cur->next;
        }
        cur->next = nullptr;
        return head;
};

方法二:头插法

初始化3个指针:

  1. result指针指向已经反转好的链表的最后一个节点,最开始没有反转,所以指向nullptr。
  2. p指针指向待反转链表的第一个节点,最开始是第一个节点等待反转,所以指向pHead。

循环执行以下操作:

  1. ListNode* temp = p->next将p的下一个节点进行保存。

  2. p->next = result将反转后的result链表作为当前节点的后续节点。

  3. result = p反转后的链表添加一个新的节点。

  4. p = temp寻找下一个待插入节点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL || pHead->next == NULL)
        	return pHead;
        ListNode* result = NULL;
        ListNode* p = pHead;
        while(p){
        	ListNode* temp = p->next;
            p->next = result;
            result = p;
            p = temp;
        }
        return result;
};

方法三:递归

递归的模板:终止条件、逻辑处理(可能有,可能没有)递归调用、逻辑处理(可能有,可能没有)。

终止条件就是链表为空或者链表没有尾节点,直接返回pHead。

递归调用是从当前节点的下一个节点开始进行,逻辑处理就是把当前的节点连接到递归之后的链表末尾

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL || pHead->next == NULL)
        	return pHead;
        ListNode* result = ReverseList(pHead->next);// 走到链表的末端
        pHead->next->next = pHead;// 将当前节点设置为后面节点的后续节点
        pHead->next = NULL;
        return result;
};

方法四:使用栈

因为栈本身是先进后出,把链表的每个节点逐个入栈,当全部入栈完之后,再逐个出栈,出栈时把出栈节点连接成为反转之后的链表。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL || pHead->next == NULL)
        	return pHead;
        ListNode* cur = pHead;
        stack<ListNode* > s;
        while(cur->next) {// 入栈
            s.push(cur);
            cur = cur->next;
        }
        ListNode* result = cur;
        while( !s.empty()) {// 出栈
            cur->next = s.top();
            cur = cur->next;
            s.pop();
        }
        cur->next = NULL;
        return result;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值