dhttps://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca
正规解法(反转链表,通过调整链表指针达到反转链表)
时间复杂度:O(n), 遍历一次链表
空间复杂度:O(1)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *pre = nullptr;
ListNode *cur = pHead;
ListNode *nex = pHead;
while(cur != nullptr){
nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
}
return pre; // 返回反转后的链表的头结点
}
};
利用vector构造链表
先用一个vector将单链表的指针都存起来,然后再构造链表。
时间复杂度: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) return nullptr;
vector<ListNode*> v;
while(pHead){
v.push_back(pHead);
pHead = pHead->next;
}
reverse(v.begin(),v.end()); // 反转vector
// 构造链表,以head为头结点。cur为head的复制结点,作为当前结点,用于构建链表。
ListNode *head = v[0];
ListNode *cur = head;
for(int i=0; i<v.size(); i++){
cur->next = v[i]; // 当前(cur)节点的下一个指针指向下一个节点
cur = cur->next; // 当前(cur)节点后移
}
cur->next = nullptr; // 切记最后一个节点的下一个指针指向nullptr
return head; // 返回反转后的链表的头结点
}
};
递归
时间复杂度:O(n),其中 n是链表的长度。需要对链表的每个节点进行反转操作。
空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 n 层。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==nullptr || pHead->next==nullptr )
return pHead;
ListNode *reverseListHead = ReverseList(pHead->next);
pHead->next->next = pHead;
pHead->next = nullptr;
return reverseListHead; // 返回反转后的链表的头结点
}
};
这里递归不好理解,下面是详细的:
https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/
/**
* 以链表1->2->3->4->5举例
*/
public ListNode reverseList(ListNode* head) {
if (head == null || head.next == null) {
/*
直到当前节点的下一个节点为空时返回当前节点
由于5没有下一个节点了,所以此处返回节点5
*/
return head; /* 第一轮(最上层)出栈:传入的head为5,由于head.next为空,于是返回该节点5, reverseListHead接收该结点5 */
}
//递归,一直递归到链表的最后一个结点,该结点就是反转后的头结点reverseListHead,即节点5。
ListNode *reverseListHead = reverseList(head.next); // 递归入栈,共5层栈。
/*
继上面的第一轮出栈后,此时head为4,于是
第二轮(第二层)出栈,head为4,head.next为5,执行head.next.next=head也就是5.next=4,
把当前节点的子节点的子节点指向当前节点
此时链表为1->2->3->4<->5,由于4与5互相指向,所以此处要断开4.next=null
此时链表为1->2->3->4<-5
返回节点5
第三轮(第三层)出栈,head为3,head.next为4,执行head.next.next=head也就是4.next=3,
此时链表为1->2->3<->4<-5,由于3与4互相指向,所以此处要断开3.next=null
此时链表为1->2->3<-4<-5
返回节点5
第四轮出栈,head为2,head.next为3,执行head.next.next=head也就是3.next=2,
此时链表为1->2<->3<-4<-5,由于2与3互相指向,所以此处要断开2.next=null
此时链表为1->2<-3<-4<-5
返回节点5
第五轮出栈,head为1,head.next为2,执行head.next.next=head也就是2.next=1,
此时链表为1<->2<-3<-4<-5,由于1与2互相指向,所以此处要断开1.next=null
此时链表为1<-2<-3<-4<-5
返回节点5
出栈完成,最终头节点5->4->3->2->1
*/
head.next.next = head;
head.next = null;
return reverseListHead; // 返回反转后的链表的头结点
}
/**
* 以链表1->2->3->4->5举例
*/
public ListNode reverseList(ListNode* head) {
if (head == null || head.next == null) {
/*
递归的“递”过程的终止条件。从 'return head;' 开始,“归”已经开始了。
“递”到最后,到达结点5,由于结点5没有下一个节点了(即5.next==null),所以此处返回节点5,即“归”5,由reverseListHead接收节点5。
*/
return head;
}
//递归,一直递归到链表的最后一个结点,该结点就是反转后的头结点reverseListHead,即节点5。
ListNode *reverseListHead = reverseList(head.next);
/*
第一轮出栈,head为5,head.next为空,返回节点5
第二轮出栈,head为4,head.next为5,执行head.next.next=head也就是5.next=4,
把当前节点的子节点的子节点指向当前节点
此时链表为1->2->3->4<->5,由于4与5互相指向,所以此处要断开4.next=null
此时链表为1->2->3->4<-5
返回节点5
第三轮出栈,head为3,head.next为4,执行head.next.next=head也就是4.next=3,
此时链表为1->2->3<->4<-5,由于3与4互相指向,所以此处要断开3.next=null
此时链表为1->2->3<-4<-5
返回节点5
第四轮出栈,head为2,head.next为3,执行head.next.next=head也就是3.next=2,
此时链表为1->2<->3<-4<-5,由于2与3互相指向,所以此处要断开2.next=null
此时链表为1->2<-3<-4<-5
返回节点5
第五轮出栈,head为1,head.next为2,执行head.next.next=head也就是2.next=1,
此时链表为1<->2<-3<-4<-5,由于1与2互相指向,所以此处要断开1.next=null
此时链表为1<-2<-3<-4<-5
返回节点5
出栈完成,最终头节点5->4->3->2->1
*/
head.next.next = head;
head.next = null;
return reverseListHead; // 返回反转后的链表的头结点
}