描述(来自牛客):

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。


数据范围:0≤n≤1000

要求:空间复杂度 O(1) ,时间复杂度 O(n) 。


如当输入链表{1,2,3}时,

经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

以上转换过程如下图所示:

4A47A0DB6E60853DEDFCFDF08A5CA249.png


解题思路:

(1)众所周知,链表是由data和next组成的,而next只能指向后续结点。


(2)如果链表只有2个结点,比如1->2,那反转的方法就是:先断开1到2的连接(即结点1的next,因为不允许1->2和2->1同时存在),然后1->NULL(因为链表的最后一个结点的next为空),最后2->1(即2的next指向1),并且第二步和第三步的顺序无所谓。


(3)扩展到3个以及更多的情况,比如1->2->3,如果还用上面的方法,就会导致当2->1之后,原有的2->3没了(因为2的next只能指向一个位置,改成1之后就找不到3了),而3只能通过它的前续结点找到,现在通过2只能找到1了,3就变成了一个无法访问的结点,这是很危险的。


(4)所以应该在修改2的next之前,就先找到3,这样2->1之后,仍然可以访问3。


(5)因此应该定义3个指针,分别表示前续,当前和后续的结点位置。每一轮修改next前,先把后续的指针更新,然后修改,最后把前续指针改成当前指针,后续指针改成当前指针,这样就能顺利进行下一轮修改了。


源代码:

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* pre = NULL;
        ListNode* cur = pHead;
        ListNode* tmp = NULL;
        while(cur != NULL){
            tmp = cur->next; // 找到后续结点
            cur->next = pre; // 修改当前next
            // 更新
            pre = cur;
            cur = tmp;
        }
        return pre; // 最后输出链表的头结点(即原链表的尾结点)
    }
};

点赞(0)
 

0.0分

3 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论