BM1反转链表
描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0\leq n\leq10000≤n≤1000
要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
示例1
输入:
{1,2,3}
返回值:
{3,2,1}
示例2
输入:
{}
返回值:
{}
说明:
空链表则输出空
双指针法
使用一个指针cur指向头结点,另一个指针初始为nullptr,然后用一个临时变量tmp保存cur->next,因为接下来需要反转cur->next。具体反转步骤为:
- tmp保存cur->next;
- cur->next指向pre;
- pre向前移动变成cur的值;
- cur向前移动变成tmp的值。
然后不断迭代。
图源牛客,侵删
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
#include <list>
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode* tmp;
ListNode* cur = pHead;
ListNode* pre = nullptr;
while(cur){
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
递归法1
和迭代法差不多,就是感觉好绕。。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
#include <list>
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur){
if(cur == nullptr) return pre;
//pre = cur;
//cur = tmp;
ListNode* tmp = cur->next;
cur->next = pre;
return reverse(cur, tmp);
}
ListNode* ReverseList(ListNode* pHead) {
return reverse(nullptr, pHead);
}
};
递归法2
大致明白思路,具体这个递归的执行过程不理解,比上个还绕,,,
半响后更新:好像又理解第二种递归法的执行了:就是pHead和pHead->next都不为空的话,就递归执行反转函数,然后接着执行当前pHead与其第二个结点的反转(把pHead的next的next指向自身,把pHead的next指向空)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
#include <list>
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == nullptr) return nullptr;
if(pHead->next == nullptr) return pHead;
ListNode* ans = ReverseList(pHead->next);
pHead->next->next = pHead;
pHead->next = nullptr;
return ans;
}
};