描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤𝑛≤10000≤n≤1000
要求:空间复杂度 𝑂(1)O(1) ,时间复杂度 𝑂(𝑛)O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
示例1
输入:
{1,2,3}
复制返回值:
{3,2,1}
复制
示例2
输入:
{}
返回值:
{}
说明:
空链表则输出空
思路:
由于指针链表只能在元素后面连接新链表,而不能直接在第一个位置上加元素,因此先排尾巴。每次将排好的尾巴连接在未排序列第一个位置后取出,从而增加一个排好的元素。
取头放尾法:将链表反转的方法,创建三个变量,一个放未取的尾,一个放排好的尾,一个取头放尾(未排的尾)、加头放尾(排好的尾)。
注意:实际在内存中只有6个节点,1-6,只是通过多个指针变换了连接方式,因此以下的示意图仅仅是便于厘清原理。
创建指针:
cur:将排好的尾巴pre加在未排的第一个元素后、从tmp取还未排的元素
tmp:存放还未排的元素
pre:存放排好了的尾巴
1. 将当前链表的第二位地址赋值给tmp:tmp = cur->next(即:tmp取链表第二位开始到结尾)
2. 将当前链表第一位连接到pre(初始为nullptr,后续为排列好的尾巴)上:cur->next=pre(即:加上排列好的尾巴,排好的元素+1)
3. 将cur赋值给pre:pre=cur(即:将排好元素+1的结果放入pre这个专门存放排好尾巴的变量)
4. 取出tmp值给cur:cur=tmp(即:将还未排的,后面的,给cur参与下一次排),如果cur为空了,即没有还未排的了,退出循环,返回排好的pre。
代码:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* ReverseList(ListNode* head) {
// write code here
if(head == nullptr)
return nullptr;
ListNode *cur = head, *tmp = nullptr, *pre = nullptr;
while (cur!=nullptr)
{
tmp = cur->next;//放尾
cur->next = pre;//取头,加头
pre = cur;//存排好的尾
cur = tmp;//取放好的尾
}
return pre;
}
};