当前位置: 首页剑指offer刷题第五期问题详情 【链表专题】剑指 Offer 24. 反转链表 本问题对应课程链接:剑指offer刷题第五期 要求: 1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。 2、给出你代码所用的时间复杂度和空间复杂度
共以下 40 个回答
两种方法都打卡成功
双指针方法,以后向指针为最终的反转表头
“””
struct ListNode* reverseList(struct ListNode* head){
// 判空
if (head NULL) {
return NULL;
}
// 处理,双指针方法,以post为反转后的头
struct ListNode *cur = head, *pre = NULL, *post = NULL;
while (cur != NULL) {
pre = cur->next;
cur->next = post;
post = cur;
cur = pre;
}
// 返回,cur最后赋值为pre,已和post断开,所以不能以此返回
return post;
}
“””
思路
解题方法
复杂度
时间复杂度:
空间复杂度:
Code
//第一种方法递归 不断的执行递归 当递归完成后还有head->next 和head->next->next 需要改变因为head->next->next 是断的 需要自行修改
//时间复杂度O(n)和空间复杂度O(n)
if(head NULL &&head->next NULL)zh
return head;
ListNode temp = reverselist(head->next)
head->next = NULL;
head->next->next = head;
return head;
//第二种原地 全部的数值进行不停的移动一位,直到移动的当前指针为空时表示转移了全部
//时间复杂度O(n)和空间复杂度O(1)
if(head NULL||head->next NULL)
reuturn head;
ListNode pre = NULL,cur = head;
while(cur!= NULL)
{
ListNode *temp = cur->next;
cur->next = pre;
pre=cur;
cur= temp;
}
return pre;
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode pre = nullptr;
ListNodecurr = head ;
ListNode* temp;
while(head)
{
temp = curr->next;
curr->next = pre;
pre = curr;
curr = temp;
}
return pre;
}
};
时间复杂度:O(N)
空间复杂度:o(1)
原地反转:
时间复杂度:o(n)
空间复杂度:o(1)
递归
时间复杂度:o(n)
空间复杂度:o(n)
原地:时间O(n),空间O(1)
递归:时间O(n),空间O(n)
struct node * reverList(struct node * head)
{
struct node * prev = NULL;
struct node * curr = head;
},该代码为原地反转,时间复杂度为o(n),空间复杂度为o(1)
//递归方式
struct node * reverList2(struct node * head)
{
//判断节点是否为空
if(head NULL || head->next NULL)
{
return head;
}
//通过创造子链,然后递归反转我们的链表节点
struct node *rev = reverList2(head->next);
head->next->next = head;
head->next = NULL;
return rev;
}//时间复杂度O(n) 空间复杂度O(n)
递归反转加原地反转
class Solution {
public ListNode reverseList2(ListNode head) {
if(head null || head.next null){
return head;
}
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
打卡
递归
迭代
/ reverseList(ListNode* head) {
//利用双指针,将尾节点通过tmp为媒介一次传递给pre;
//时间复杂度为0(n);
//空间复杂度为o(1);
#include
class Solution {
public:
ListNode
ListNode pre=NULL,cur=head;
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode reverseList(ListNode* head) {
/if(headNULL||head->nextNULL){
return head;
}
ListNode *t=reverseList(head->next);
head->next->next=head;
head->next=NULL;
return t;/ //递归:时间复杂度O(n),空间复杂度O(n)
if(headNULL||head->nextNULL){
return head;
}
ListNode pre=NULL,cur=head;
while(cur!=NULL){
ListNode *t=cur->next;
cur->next=pre;
pre=cur;
cur=t;
}
return pre; //原地反转:时间复杂度O(n),空间复杂度O(1)
}
};
时间复杂度:o(n),空间复杂度o(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode reverseList(ListNode* head) {
ListNode *rhead = nullptr;
ListNode *cur = head;
while (cur) {
ListNode *next = cur->next;
cur->next = rhead;
rhead = cur;
cur = next;
}
return rhead;
}
};
原地反转:
思路:使用三个指针,一个表示反转后的链表的头指针,一个表示待反转剩余的节点组成的链表的头指针,一个表示辅助节点
时间复杂度:O(n),空间复杂度:O(1)
class Solution {
public ListNode reverseList(ListNode head) {
if(head null || head.next null) {
return head;
}
ListNode cur = null;
ListNode pre = head;
ListNode temp = head;
while(temp != null) {
temp = pre.next;
pre.next = cur;
cur = pre;
pre = temp;
}
return cur;
}
}
递归反转
思路:每次递归传入链表的下一个节点,每次让参数节点的next指向参数节点实现链表反转,每次返回值是头节点,最后一次递归一定是原来的尾节点也就是反转后链表的头节点,递归结束条件是当传递的节点没有下一个接待你时返回该节点(因为需要让参数接点的next指向参数节点,参数节点指向null)。
时间复杂度:O(n),空间复杂度:O(n)
class Solution {
public ListNode reverseList(ListNode head) {
// head null,只是防止第一次调用时head为null,后面每次递归head都不会为null
if(head null || head.next null) {
return head;
}
ListNode node = reverseList(head.next);
head.next.next = head;
head.next = null;
// node为原来链表的尾结点,也就是反转后链表的头节点
return node;
}
}
空间复杂度 O(1) 时间复杂度为 O(N)
时间复杂度O(n)空间复杂度O(n)
思路是递归
”’java
class Solution {
public ListNode reverseList(ListNode head) {
if(head null)
return head;
}
非递归
ListNode* reverseList(ListNode* head) {
if(head nullptr) return nullptr;
ListNode* dummy = new ListNode(0);
dummy->next = nullptr;
递归
ListNode* reverseList(ListNode* head) {
if(head nullptr) return nullptr;
if(head->next nullptr){
return head;
}
时间O(n) 空间O(1), O(n)
头插法
时间复杂度O(n)
空间复杂度O(1)
/**
*打卡
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head null || head.next null) return head;
}
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head NULL || head->next NULL){
return head;
}
ListNode* cur;
ListNode* pre;
ListNode* tmp;
cur = head;
pre = NULL;
while(cur){
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
时间复杂度O(n),空间复杂度O(1)
分别使用两个方法进行解题。
+ 方法一:双指针迭代
时间复杂度O(N),空间复杂度O(1)
时间复杂度O(N),
空间复杂度O(N) : 遍历链表的递归深度达到 N ,系统使用 O(N) 大小额外空间。
时间复杂度:O(N), 空间复杂度:O(1)
用中间变量记录下一个节点
原地反转
时间复杂度:O(N), 空间复杂度:O(1)
递归
空间复杂度 O(1)
时间复杂度O(N)
本题是主要是两个问题:
1.在何处写链表反转代码,答案是在后续位置而核心代码就是
遇到类似问题可以先把这个代码写完
2、如何把结尾的头返回过来,比较妙的写法是这个return head,因为这样结尾的代码则为return 结尾的代码
而tmp的值在所有递归中都在传递这个值
时间On ,空间O1
时间复杂度O(n),空间复杂度O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode reverseList(ListNode* head) {
if (head nullptr) {
return nullptr;
}
ListNode *last = nullptr;
ListNode *tmp = head->next;
ListNode *cur = head;
while (tmp != nullptr) {
cur->next = last;
last = cur;
cur = tmp;
tmp = cur->next;
}
cur->next = last;
return cur;
}
};
時間複雜度: O(n) 空間複雜度: O(n)
思路: 一樣利用遞歸來解, 首先取得最尾端的node, 並在後序遍歷位置反轉當前node, 最後回傳最尾端node即為結果
1、栈
思路:利用栈存储节点值,出栈到新链表返回
时间复杂度O(n),空间复杂度O(n)
注意的是一定要提前记录好cur下一个节点的地址,因为将next赋值之后就断了
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head null) return null;
if(head.next null) return head;
ListNode cur = head;
// ListNode next_node = cur.next;
ListNode pre = new ListNode(-1);
pre.next = null;
while(cur.next!=null){
ListNode temp = cur.next;
cur.next = pre.next;
pre.next = cur;
cur = temp;
}
cur.next = pre.next;
return cur;
}
}
“`python
用栈写的
Definition for singly-linked list.
class ListNode:
def init(self, x):
self.val = x
self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head None: return None
tmp = ListNode(-1)
tmp.next = head
//创建俩,一个原表一个空表,然后借用中间值pnext前插发
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *p1=head;
struct ListNode *p2=NULL;
while(p1){
struct ListNode *pnext=p1->next;
// p2->val=p1->val;
// p2->next=p1->next;
// p1=p1->next;
p1->next=p2;
p2=p1;
p1=pnext;
// free(pnext);
}
return p2;
}
时间复杂度O(n)空间复杂度O(1)
这里用的是原地翻转,用了两个指针,prev和next。
原地反转;
时间复杂度O(n)
空间复杂度O(1)