力扣:LCR 024.反转链表

1、题目要求

给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。

 

示例 1:

 

4c48036235015ae66efd736264b3ca0d.jpeg

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

 

f072058ab32567bc728c2287d69f2a92.jpeg

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

 

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

 

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

 

2、题目分析

题目告诉我们这道题有两种解法:迭代法和递归法

迭代法:通过不同的指针变量,遍历整个链表,并在遍历的过程中将数据逆置并存放在一个新的链表中。

递归法:通过调用reversList函数,将链表后面的数据逆置,最后达到整个链表逆置的目的。(将一个链表head逆置,就相当于将head->next的所有数据逆置,将head->next的1所有数据逆置,就相当于将head->next->next的所有数据逆置······最后再依次返回即可)

 

3、代码实现

迭代法:

方法一

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode*newHead=new ListNode();    //创建新的链表
        newHead->next=NULL;                 //新链表后置为空
        ListNode*p=head,*q=head;            //两个游动的指针变量,先同时指向head
        while(p){                           //把p当作要取的数
            q=q->next;                      //q变为p的后一个数,防止p丢失
            p->next=newHead->next;          //把p链接到newHead上
            newHead->next=p;                
            p=q;                            //把p移动到q位置上
        }
        return newHead->next;
    }
};

方法二

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //ListNode*newHead=new ListNode();    
        //newHead->next=NULL;                 
        ListNode*curr=head,*prev=NULL;            
        while(curr){  
            ListNode*next=curr->next;                         
            curr->next=prev;
            prev=curr;
            curr=next;                          
        }
        return prev;
    }
};

递归法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head||!head->next) return head;   //先判断是否为空或者只有一个结点,是的话直接返回
        ListNode*newHead=reverseList(head->next);//开始递归
        head->next->next=head;           ①//每次递归要将传入的链表的头节点拿到逆置后的链表的尾部
        head->next=NULL;                 ②//将逆置后的尾结点(即原来的头结点)后置为空
        return newHead;
    }
};

①②解释:例如1 2 3 4 5 ,我们传入reversList函数后,2 3 4 5 逆置变为 5 4 3 2 ,此时5就是newHead的头结点,而我们需要将原来的头结点head放到newHead的最后面,也就是2的后面,此时2在原结点中还是head->next,那么head->next->next=head就将head移到最后了,但移动后最后结点的后续不为空,所以我们用head->next=NULL将newHead最后置为空。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值