LeetCode | 206.反转链表
LeetCode 是著名的练习数据结构与算法的网站,很多学习程序设计的人都在刷上面的题来巩固和提高自己的数据结构以及算法的能力。同时,该网站的很多数据结构及算法题都是面试中的真题。
我刷过的题目不算多,我准备把我做过的题目再逐步的整理一下。虽然之前也有整理过,但是基本上是把题目和答案粘贴上就算完事了。这样做其实并没有把解题的过程留下,那么也就既起不到总结的作用,也算不上是分享了。因此,我还是打算认真的整理一下。
我的整理不会按照题目的顺序去整理,我只能是按照我已经完成的题目去整理。今天整理的是第 206 题 “反转链表”。
题目描述
题目直接从 LeetCode 拿来,题目如下:
上面的题就是 反转链表 题目的截图,同时 LeetCode 给出了一个函数的定义,然后要求实现反转链表的函数体。函数定义如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
}
从函数定义可以看出,它是一个单链表,单链表的特点是当前结点通过其指针域可以找到下一个结点,而无法通过当前结点找到它的上一个结点。
问题分析
反转单链表的思路还是比较简单的,关键是代码的实现,我们来简单的分析一下代码要完成的功能。
把问题的规模缩小到 3 个结点,情况如下:
1 -> 2 -> 3 -> NULL
反转链表,后的情况如下:
3 -> 2 -> 1 -> NULL
reverseList 的参数 head 指向了链表的 1 结点,只要我们循环遍历整个链表,并且让当前结点的指针指向前一个结点即可。但是单链表只能沿着一个方向进行遍历,无法找到上一个结点。因此,在进行遍历的时候,必须要有两个指针,一个指针用来指向当前元素、另一个指针用来指向当前元素的上一个元素,两个指针同时移动,这样让当前元素的指针就可以指向上一个元素了。
但是,这样就会有另外一个问题,当前元素的指针是指向下一个元素的,如果将当前元素的指针指向了上一个元素,那么当前元素和下一个元素就断链了,也就是无法找到当前元素的下一个元素了。那么,只要在当前元素的指针指向上一个元素之前,就先让另外一个指针指向当前元素的下一个元素,那么就可以了。
比如,当前元素是 2 结点,指向 2 结点的指针为 cur。指向上一个结点的指针为 per,也就是说 per 指针指向 1 结点。2 结点的下一个结点是 3 结点,在 2 结点的指针指向 1 结点之前,让 tmp 指向下一个结点。
当然了,思路是这样的,三个指针的关系也是这样的,但是实现代码的时候只要能维持 3 个指针之间的关系就可以了。
代码实现
代码还是比较简单的,代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
/* 指向第一个结点 */
struct ListNode *cur = head;
struct ListNode *per = NULL;
struct ListNode *tmp = NULL;
/* 判断当前结点是否为NULL */
while (cur) {
/* 将当前结点保存到tmp中 */
tmp = cur;
/* 当前结点移动到下一个结点 */
cur = cur->next;
/* 当前结点的指针指向上一个结点 */
tmp->next = per;
/* 上一个结点指向当前结点 */
per = tmp;
}
return per;
}
提交结果
在写完 reverseList 函数体后,点击右下角的 “执行代码”,然后观察 “输出” 和 “预期结果” 是否一致,一致的话就点击 “提交” 按钮。点击 “提交” 按钮后,系统会使用更多的测试用例来测试我们写的函数体,如果所有的测试用例都通过了,那么就会给出 “通过” 的字样,如果没有通过,会给出失败的那一组测试用例,我们继续修改代码。我们以上代码 “提交” 以后的截图如下:
我的代码是否最优,我并不清楚,我也没有去阅读别人的代码和解题思路。如果有不懂的,欢迎给我留言,我们一起讨论。
- 非常强悍并实用的双机热备+负载均衡线上方案
- Apache 压力测试工具ab
- SQL之收集SQL Server线程等待信息
- 聚合索引(clustered index) / 非聚合索引(nonclustered index)
- 域名资讯:单词域名can.com以15.5万美金成功交易
- jQuery无缝图片横向(水平)/竖向(垂直)滚动
- Centos下MooseFS(MFS)分布式存储共享环境部署记录
- MFS+Keepalived双机高可用热备方案操作记录
- Docker容器学习梳理-容器时间跟宿主机时间同步
- AS1.0(2.0)中的XML示例
- kvm虚拟机日常操作命令梳理
- mongodb 总结
- 关于微信小程序内置组件swiper,circular使用分享
- zabbix问题记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android嵌套滑动冲突的解决方法
- Android应用图标上的小红点Badge实践代码
- 详解Android studio中正确引入so文件的方法
- Android ViewFlipper的详解及实例
- Android编程实现拍照功能的2种方法分析
- 在Ubuntu/Linux环境下使用MySQL开放/修改3306端口和开放访问权限
- 10大HBase常见运维工具整理小结
- Android实现扫一扫识别数字功能
- 通过SSH连接本地linux虚拟机的过程记录
- 实现Android 获取cache缓存的目录路径的方法
- Android 消息分发使用EventBus的实例详解
- 详解Android实现定时器的几种方法
- Android 实现带进度条的WebView的实例
- Android单元测试之对Activity的测试示例
- Android开发之手势检测及通过手势实现翻页功能的方法