C++链表02:反转链表
1.背景
大家好,我是酒馆店小二。
力扣206.翻转链表。
题意:反转一个单链表。
示例:
输入: 2->3->4->5->NULL
输出: 5->4->3->2->NULL
2.迭代
如图,
- 定义
pre
指针,初始化为nullptr
; - 定义
cur
指针,指向头结点; - 定义
temp
指针,指向cur->next
节点,为什么要指向这个节点?因为接下来要改变cur->next
的指向,将cur->next
指向pre
; - 重复执行上述操作,不断后移
pre
和cur
指针,直到cur
指向nullptr
,循环结束,链表反转完毕,返回pre
指针即可。
说一千道一万,没有代码都不算。
迭代代码:
/*** 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) {}* };*/
ListNode* reverseList(ListNode* head) {ListNode* pre = nullptr; // 定义 pre 指针,初始化为 nullptr;ListNode* cur = head; // 定义 cur 指针,指向头结点;while(cur) {ListNode* tmp = cur->next; // 定义 temp 指针,指向 cur->next 节点cur->next = pre;pre = cur; // 后移 pre 和 cur 指针cur = tmp;}return pre;
}
3.递归
递归版本稍微复杂一些,其关键在于反向工作。假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?
假设链表为:
n1→…→n k−1→n k→n k+1 →…→n m →∅
若从节点 n k+1 到 n m已经被反转,而我们正处于 n k 。
n1 →…→n k−1 →n k →n k+1 ←…←n m
我们希望 n k+1的下一个节点指向 n k。
所以,nk→next→next = nk。
需要注意的是 n 1的下一个节点必须指向 ∅。如果忽略了这一点,链表中可能会产生环。
ListNode* reverseList(ListNode* head) {if (!head || !head->next) return head;// 递归调用,翻转第二个节点开始往后的链表ListNode* newHead = reverseList(head->next);// 反转头节点与第二个节点的指向head->next->next = head;// head节点指针指为空,因为它已经被它的下一个节点指向了,理论上它就是尾结点// 因为通过递归操作找到的就是尾结点,并且反转尾结点head->next = nullptr;return newHead;
}
4.进阶:反转链表内指定区间
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n)O(n),空间复杂度 O(1)O(1)O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL,m = 2,n = 4,
返回 1→4→3→2→5→NULL。
解题思路:
- 判断参数 head 是否为空,若空则直接返回;判断m是否等于 n,相等则无需进行操作,直接返回;
- 创建一个头结点 dummyHead ,以便对整个链表的操作实现统一;
- 指针begin初始化为头节点 dummyHead,begin 将作为待反转链表第一个结点的前驱指针。然后通过变量 i (初始化为 0 )记录当前遍历的结点个数,顺序遍历链表的前 m -1个结点时,begin 不断向前移动,最终指向第 m - 1 个结点;
- 指针 start 指向待反转链表的第一个结点,初始化为 begin->next ;指针 finish 指向待反转链表的最后一个结点,初始化为 begin。然后在顺序遍历到第 n 个结点的过程中,finish不断向前移动,直到指向第 n 个结点。
- 指针 end 指向待反转链表的最后一个结点的下一个位置;
反转链表:
- 初始时,指针 pre 指向 start,指针 cur 指向 start->next,begin->next = nullptr,finish->next = nullptr;
- 反转过程: tmp = cur->next; cur->next = pre;pre = cur;cur = tmp
- 结束条件:cur == finish
- 最后一步:将反转后的链表与其余 begin 之前的链表和 end 之后的链表进行连接:
begin->next = finish; start->next = end;
ListNode *reverseBetween(ListNode *head, int m, int n) {if (!head || m == n) return head;ListNode *dummyHead = new ListNode(-1);dummyHead->next = head; // 创建链表的头结点ListNode *begin = dummyHead; // begin 初始化为虚拟头结点int i = 0;while (i < m - 1) {begin = begin->next; // 循环结束,begin 指向第 m - 1个节点,即待反转链表前一个节点++i;}ListNode *start = begin->next;ListNode *finish = begin;while (i < n) {finish = finsh->next; // 循环结束,finish 指向第 n 个节点,即待反转链表最后一个节点++i;}ListNode *end = finish->next; // end 指向待反转链表最后一个节点之后的一个节点ListNode *pre = start;ListNode *cur = start->next;begin->next = nullptr;finish->next = nullptr;while (pre != finish) {ListNode *tmp = cur->next;cur->next = pre;pre = cur;cur = tmp;}begin->next = finish;start->next = end;head = dummyHead->next;delete dummyHead;return head;
}
当时轻别意中人,山长水远知何处。
2022.3.23
C++链表02:反转链表相关推荐
- 输入一个链表,反转链表后,输出新链表的表头(ACM格式)(美团面试题)
输入一个链表,反转链表后,输出新链表的表头 其实这道题就是一个反转链表的题,但是因为自己不会建立链表,所以特地采用ACM的格式试着编写一下,这也美团给我出的一道实习算法题. public class ...
- 【算法】输入一个链表,反转链表后,输出新链表的表头。
题目 输入一个链表,反转链表后,输出新链表的表头. 示例1 输入 {1,2,3} 返回值 {3,2,1} 说明:本题目包含复杂数据结构ListNode Java /* public class Lis ...
- 链表之反转链表,万金油的解题方法(java求解)
链表之反转链表,一招鲜吃遍天(java求解) 内容目录 链表之反转链表,一招鲜吃遍天(java求解) 解题万金油 栗子1:反转整个链表 栗子2:反转某个区间内的链表 栗子3:按照k为一组,反转某个区间 ...
- 【剑指Offer专题】链表系列:从尾到头打印链表、反转链表、回文链表、合并两个排序的链表(C++和Python实现)...
关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 剑指Offer(三):从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每 ...
- python反转链表_206. 反转链表(Python)
题目 难度:★★☆☆☆ 类型:链表 反转一个单链表. 进阶: 你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 示例 输入: 1->2->3->4->5->NUL ...
- day03链表基础_移除链表元素_设计链表_反转链表
链表理论基础 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思). 链表的入口节点称 ...
- Suzy找到实习了吗Day 3 | 链表开始啦 203移除链表元素 707设计链表 206 反转链表
定义链表的结构 class ListNode:def __init__(self, val, next=None): #构造函数self.val = valself.next = next 尾部nod ...
- leetcode链表之反转链表
本文主要有三道题,都是关于反转链表的算法题,由浅入深. 文章出现的代码都是python3 206.反转链表 题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表. 示例1: 输入:h ...
- 剑指offer算法题,输入一个链表,反转链表后,输出新链表的表头。
链表的算法题一直做的浑浑噩噩的,为了避免忘记以及能够及时的温故知新,所以将本次的解答记录如下: 话不多说,先贴代码: /* public class ListNode {int val;ListNod ...
- 输入一个链表,反转链表后,输出新链表的表头。
代码来自Java程序员面试笔试宝典 主要思想: pre cur next三个节点 /* public class ListNode {int val;ListNode next = null; ...
最新文章
- [bzoj2213][Poi2011]Difference_动态规划
- 鸿蒙系统2019发布会,直击丨2019华为开发者大会 “鸿蒙”系统今日正式发布!...
- 音视频技术开发周刊 | 203
- 软件建模——第3章 项目前期
- Sublime Text3常用基本操作
- js ---- 对象去重
- 推荐12个最好的 JavaScript 图形绘制库
- Vue 项目在 IE11 中数据更改后页面数据无变化
- 音乐标签编辑器 Meta 2.0.0 for Mac
- 开发基于大数据平台的搜索引擎
- ORBSLAM关键帧的筛选和插入
- 如何通过一个字符串来实例化一个类_Spring官网阅读(一)容器及实例化
- 关于GetTickCount函数的用法
- 【经验】vmware虚拟机只能使用鼠标无法使用键盘、装VMware-Tools无法复制粘贴的可能解决办法
- 一文读懂什么是绿色工厂以及绿色工厂建设细解
- MATLAB-三维插值运算
- sql注入登陆(菜鸟级)
- kibana java_Kibana安装及使用说明
- 相册计算机软件,电脑相册制作软件免费版,windows自带安全又免费相册制作软件...
- 如何更快地渲染?深入了解3D渲染性能的指南!(5)