Python算法题集_反转链表

 Python算法题集_反转链表

  • 题41:反转链表
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【列表反转】
    • 2) 改进版一【直接赋值】
    • 3) 改进版二【递归大法】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题41:反转链表

1. 示例说明

  • 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

    示例 1:

    Python算法题集_反转链表_第1张图片

    输入:head = [1,2,3,4,5]
    输出:[5,4,3,2,1]
    

    示例 2:

    Python算法题集_反转链表_第2张图片

    输入:head = [1,2]
    输出:[2,1]
    

    示例 3:

    输入:head = []
    输出:[]
    

    提示:

    • 链表中节点的数目范围是 [0, 5000]
    • -5000 <= Node.val <= 5000

    **进阶:**链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?


2. 题目解析

- 题意分解

  1. 本题为单向链表的反转
  2. 本题的主要计算有2处,1是链表遍历,2是指针修改
  3. 基本的解法是采用列表保存节点,然后单层循环反转,所以基本的时间算法复杂度为O(n)

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以直接进行节点的指针微调

    2. 可以用递归法进行反转,不过递归法一向是重型代码,性能不会太好


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题很难超时,本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【列表反转】

马马虎虎,超过44%Python算法题集_反转链表_第3张图片

import CheckFuncPerf as cfp

def reverseList_base(head):
 if head == None:
     return None
 nodelist = []
 nodecurr = head
 while nodecurr is not None:
     nodelist.append(nodecurr)
     nodecurr = nodecurr.next
 for iIdx in range(len(nodelist)):
     if iIdx == 0:
         nodelist[iIdx].next = None
     else:
         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%Python算法题集_反转链表_第4张图片

import CheckFuncPerf as cfp

def reverseList_ext1(head):
 nodeprev = None
 nodecurr = head
 while nodecurr is not None:
     next_node = nodecurr.next
     nodecurr.next = nodeprev
     nodeprev = nodecurr
     nodecurr = next_node
 return nodeprev

result = cfp.getTimeMemoryStr(reverseList_ext1, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 运行结果
函数 reverseList_ext1 的运行时间为 2.99 ms;内存使用量为 0.00 KB 执行结果 = 0

3) 改进版二【递归大法】

递归法从来都不是讲效率的,没办法 马马虎虎,超过58%Python算法题集_反转链表_第5张图片

import CheckFuncPerf as cfp

def reverselist_ext2(head):
 def revnode(node, pre):
     if not node:
         return pre
     revn = revnode(node.next, node)
     node.next = pre
     return 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 = head
    for num in data:
        new_node = ListNode(num)
        current_node.next = new_node
        current_node = new_node
    return 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 ~

你可能感兴趣的:(Python,python,算法,链表,leetcode,反转链表)