Python算法题集_反转链表
- 题41:反转链表
- 1. 示例说明
- 2. 题目解析
- - 题意分解
- - 优化思路
- - 测量工具
- 3. 代码展开
- 1) 标准求解【列表反转】
- 2) 改进版一【直接赋值】
- 3) 改进版二【递归大法】
- 4. 最优算法
本文为Python算法题集之一的代码示例
题41:反转链表
1. 示例说明
-
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
**进阶:**链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
- 链表中节点的数目范围是
2. 题目解析
- 题意分解
- 本题为单向链表的反转
- 本题的主要计算有2处,1是链表遍历,2是指针修改
- 基本的解法是采用列表保存节点,然后单层循环反转,所以基本的时间算法复杂度为O(n)
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
可以直接进行节点的指针微调
-
可以用递归法进行反转,不过递归法一向是重型代码,性能不会太好
-
- 测量工具
- 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块- 本题很难超时,本地化超时测试用例自己生成,详见【最优算法章节】
3. 代码展开
1) 标准求解【列表反转】
马马虎虎,超过44%
import CheckFuncPerf as cfpdef reverseList_base(head):if head == None:return Nonenodelist = []nodecurr = headwhile nodecurr is not None:nodelist.append(nodecurr)nodecurr = nodecurr.nextfor iIdx in range(len(nodelist)):if iIdx == 0:nodelist[iIdx].next = Noneelse:nodelist[iIdx].next = nodelist[iIdx-1]return nodelist[-1]result = cfp.getTimeMemoryStr(reverseList_base, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))# 运行结果
函数 reverseList_base 的运行时间为 9.00 ms;内存使用量为 336.00 KB 执行结果 = 19999
2) 改进版一【直接赋值】
直接对节点进行赋值 指标优良,超过91%
import CheckFuncPerf as cfpdef reverseList_ext1(head):nodeprev = Nonenodecurr = headwhile nodecurr is not None:next_node = nodecurr.nextnodecurr.next = nodeprevnodeprev = nodecurrnodecurr = next_nodereturn nodeprevresult = cfp.getTimeMemoryStr(reverseList_ext1, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))# 运行结果
函数 reverseList_ext1 的运行时间为 2.99 ms;内存使用量为 0.00 KB 执行结果 = 0
3) 改进版二【递归大法】
递归法从来都不是讲效率的,没办法 马马虎虎,超过58%
import CheckFuncPerf as cfpdef reverselist_ext2(head):def revnode(node, pre):if not node:return prerevn = revnode(node.next, node)node.next = prereturn revn return revnode(head, None)result = cfp.getTimeMemoryStr(reverselist_ext2, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))# 运行结果 递归层次超过990,溢出报错
Traceback (most recent call last):......
[Previous line repeated 991 more times]
RecursionError: maximum recursion depth exceeded
4. 最优算法
根据本地日志分析,最优算法为第2种reverseList_ext1
# 超时测试代码
nums = [ x for x in range(20000)]
def generateOneLinkedList(data):head = ListNode()current_node = headfor num in data:new_node = ListNode(num)current_node.next = new_nodecurrent_node = new_nodereturn head.next
ahead = generateOneLinkedList(nums)
result = cfp.getTimeMemoryStr(reverseList_base, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))# 算法本地速度实测比较
函数 reverseList_base 的运行时间为 9.00 ms;内存使用量为 336.00 KB 执行结果 = 19999
函数 reverseList_ext1 的运行时间为 2.99 ms;内存使用量为 0.00 KB 执行结果 = 0
函数 reverseList_ext2 ==> 递归层次超过990,溢出报错,剥夺资格,囧
Traceback (most recent call last):......[Previous line repeated 991 more times]
RecursionError: maximum recursion depth exceeded
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~