剑指offer反转链表

1.题目

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

来源:剑指offer
链接:https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=13&tqId=11168&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

2.我的题解

反转操作,最容易想到的就是使用栈,先一个一个入栈,再依次出栈,即可实现反转。
注意:

  • 先判断是否为空
  • 最后一个节点要指向NULL,否则造成链表死循环。
  • 该方法耗费额外空间O(n)
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL)return NULL;
        ListNode * res = pHead;
        stack<ListNode *> s;
        while(res){
            s.push(res);
            res=res->next;
        }
        
        pHead=s.top();
        s.pop();
        res=pHead;
        while(!s.empty()){
            res->next=s.top();
            res=res->next;
            s.pop();
        }
        res->next=NULL;//没有这句会死循环
        return pHead;
    }
};

3.别人的题解

3.1 三指针法

使用pre,cur,next三个指针,既能反转当前节点,又不会丢失后续链表。

步骤状态
0在这里插入图片描述
1在这里插入图片描述
last在这里插入图片描述
/*
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 * pre = NULL, *cur = pHead, *next = cur->next;
        while (cur) {
            cur->next = pre;
            pre = cur;
            cur = next;
            if(next)next = next->next;
        }
        return pre;
    }
};

这里注意,结束时next指针已经偏移出两个单位了,但其实最多偏移一个单位(即NULL),之后再想向后偏移就会报错,所以要加一个判断:if(next)next = next->next;
另一种解决方法:开始时令next=cur,在循环里第一步让next=cur->next

ListNode* ReverseList(ListNode* pHead) {
	if (pHead == NULL || pHead->next == NULL)return pHead;
	ListNode * pre = NULL, *cur = pHead, *next = cur;
	while (cur) {
		next = cur->next;
		cur->next = pre;
		pre = cur;
		cur = next;
	}
	return pre;
}

3.2 递归法

有这个想法但一时间没有想透彻。最后百度了才搞懂。参考1 ,贴一波图1

步骤状态
输入输出在这里插入图片描述
递归表示在这里插入图片描述
解决子问题在这里插入图片描述
递归后的操作在这里插入图片描述在这里插入图片描述
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL || pHead->next==NULL)return pHead;
        ListNode * tmp = ReverseList(pHead->next);
        pHead->next->next = pHead;
        pHead->next=NULL;
        return tmp;
    }
};

3.3 头插法

使用辅助节点,遇到一个节点就使用头插操作,最后返回辅助节点的下一个节点。
每次循环需要记录的是原链表的下一个节点。

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode * head = new ListNode(0);
        ListNode *next=pHead;
        while(pHead){
            next=pHead->next;
            pHead->next = head->next;
            head->next=pHead;
            pHead=next;
        }
        return head->next;
    }
};

4.总结与反思

(1)简单的链表,多样的解法。


  1. 使用递归反转链表 ↩︎ ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值