Python算法题集_分割回文串
- 题131:分割回文串
- [1. 示例说明](#1. 示例说明)
- [2. 题目解析](#2. 题目解析)
-
- [- 题意分解](#- 题意分解)
- [- 优化思路](#- 优化思路)
- [- 测量工具](#- 测量工具)
- [3. 代码展开](#3. 代码展开)
-
- 1) 标准求解【参数回退回溯+单行回文检测】 标准求解【参数回退回溯+单行回文检测】)
- 2) 改进版一【参数回退回溯+lambda回文检测】 改进版一【参数回退回溯+lambda回文检测】)
- 3) 改进版二【参数回退回溯+函数回文检测】 改进版二【参数回退回溯+函数回文检测】)
- 4) 改进版三【堆栈回退回溯+函数回文检测】 改进版三【堆栈回退回溯+函数回文检测】)
- [4. 最优算法](#4. 最优算法)
- [5. 相关资源](#5. 相关资源)
本文为Python算法题集之一的代码示例
题131:分割回文串
1. 示例说明
-
给你一个字符串
s
,请你将s
分割成一些子串,使每个子串都是 回文串 。返回s
所有可能的分割方案。回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a" 输出:[["a"]]
提示:
1 <= s.length <= 16
s
仅由小写英文字母组成
2. 题目解析
- 题意分解
- 本题是检测字符串中的所有回文串
- 基本的设计思路是通过回溯法遍历本字符串所有可能子串,检测是否回文
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
回溯算法过程中进行参数数量空值,并尝试切换值传递、引用传递,回退方面可以尝试参数回退、堆栈回退
-
回文检测算法可以想想不同实现方式
-
- 测量工具
- 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块- 本题本地化超时测试用例自己生成,详见章节【最优算法】,代码文件包含在【相关资源】中
3. 代码展开
1) 标准求解【参数回退回溯+单行回文检测】
使用参数回退实现回溯,回文检测采用单行代码
页面功能测试,马马虎虎,超过39%
python
import CheckFuncPerf as cfp
class Solution:
def partition_base(self, s):
def backtrack(s, result, path):
if not s:
result.append(path)
return
for iIdx in range(1, len(s) + 1):
if s[:iIdx] == s[:iIdx][::-1]:
backtrack(s[iIdx:], result, path + [s[:iIdx]])
result = []
backtrack(s, result, [])
return result
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.partition_base, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 partition_base 的运行时间为 5269.33 ms;内存使用量为 212320.00 KB 执行结果 = 601812
2) 改进版一【参数回退回溯+lambda回文检测】
使用参数回退实现回溯,回文检测改为lambda函数
页面功能测试,性能一般,超过75%
python
import CheckFuncPerf as cfp
class Solution:
def partition_ext1(self, s):
isPalindrome = lambda s: s == s[::-1]
def backtrack(s, result, path):
if not s:
result.append(path)
return
for i in range(1, len(s) + 1):
if isPalindrome(s[:i]):
backtrack(s[i:], result, path + [s[:i]])
result = []
backtrack(s, result, [])
return result
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.partition_ext1, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 partition_ext1 的运行时间为 4536.02 ms;内存使用量为 212004.00 KB 执行结果 = 601812
3) 改进版二【参数回退回溯+函数回文检测】
使用参数回退实现回溯,回文检测改为函数,并在函数中逐步进行终止判断
页面功能测试,性能一般,超过73%
python
import CheckFuncPerf as cfp
class Solution:
def partition_ext2(self, s):
def isPalindrome(s):
ileft, iright = 0, len(s) - 1
while ileft < iright:
if s[ileft] != s[iright]:
return False
ileft += 1
iright -= 1
return True
def backtrack(s, result, path):
if not s:
result.append(path)
return
for iIdx in range(1, len(s) + 1):
if isPalindrome(s[:iIdx]):
backtrack(s[iIdx:], result, path + [s[:iIdx]])
result = []
backtrack(s, result, [])
return result
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.partition_ext2, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 partition_ext2 的运行时间为 5435.21 ms;内存使用量为 208024.00 KB 执行结果 = 601812
4) 改进版三【堆栈回退回溯+函数回文检测】
使用参数回退实现回溯,回文检测改为函数,并在函数中进行终止判断
页面功能测试,马马虎虎,超过34%
python
import CheckFuncPerf as cfp
class Solution:
def partition_ext3(self, s):
result, path = [], []
def isPalindrome(s):
ileft, iright = 0, len(s) - 1
while ileft < iright:
if s[ileft] != s[iright]:
return False
ileft += 1
iright -= 1
return True
def back_track(s, index):
if index == len(s):
result.append(path[:])
return
for iIdx in range(index, len(s)):
if isPalindrome(s[index:iIdx+1]):
path.append(s[index:iIdx+1])
back_track(s, iIdx+1)
path.pop()
back_track(s, 0)
return result
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.partition_ext3, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 partition_ext3 的运行时间为 5541.26 ms;内存使用量为 207644.00 KB 执行结果 = 601812
4. 最优算法
根据本地日志分析,最优算法为第2种方式【参数回退回溯+lambda回文检测】 partition_ext1
本题大概有以下结论:
- 回文检测中,函数和Python代码直接执行性能相近,
lambda
函数性能最好 - 参数回退和堆栈回退实现的回溯算法性能相近
python
stemplete, ilen = 'abcdeedcba', 5
checkstr = ''.join([stemplete] * ilen)
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.partition_base, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.partition_ext1, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.partition_ext2, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.partition_ext3, checkstr)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 算法本地速度实测比较
函数 partition_base 的运行时间为 5269.33 ms;内存使用量为 212320.00 KB 执行结果 = 601812
函数 partition_ext1 的运行时间为 4536.02 ms;内存使用量为 212004.00 KB 执行结果 = 601812
函数 partition_ext2 的运行时间为 5435.21 ms;内存使用量为 208024.00 KB 执行结果 = 601812
函数 partition_ext3 的运行时间为 5541.26 ms;内存使用量为 207644.00 KB 执行结果 = 601812
5. 相关资源
本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_分割回文串)
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~