【python】Leetcode每日一题-扰乱字符串
【python】Leetcode每日一题-扰乱字符串
【题目描述】
使用下面描述的算法可以扰乱字符串 s 得到字符串 t :
如果字符串的长度为 1 ,算法停止
如果字符串的长度 > 1 ,执行下述步骤:
在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。
随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。
在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算法。
给你两个 长度相等 的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。如果是,返回 true ;否则,返回 false 。
示例1:
输入:s1 = "great", s2 = "rgeat"
输出:true
解释:s1 上可能发生的一种情形是:
"great" --> "gr/eat" // 在一个随机下标处分割得到两个子字符串
"gr/eat" --> "gr/eat" // 随机决定:「保持这两个子字符串的顺序不变」
"gr/eat" --> "g/r / e/at" // 在子字符串上递归执行此算法。两个子字符串分别在随机下标处进行一轮分割
"g/r / e/at" --> "r/g / e/at" // 随机决定:第一组「交换两个子字符串」,第二组「保持这两个子字符串的顺序不变」
"r/g / e/at" --> "r/g / e/ a/t" // 继续递归执行此算法,将 "at" 分割得到 "a/t"
"r/g / e/ a/t" --> "r/g / e/ a/t" // 随机决定:「保持这两个子字符串的顺序不变」
算法终止,结果字符串和 s2 相同,都是 "rgeat"
这是一种能够扰乱 s1 得到 s2 的情形,可以认为 s2 是 s1 的扰乱字符串,返回 true
示例2:
输入:s1 = "abcde", s2 = "caebd"
输出:false
示例3:
输入:s1 = "a", s2 = "a"
输出:true
提示:
s1.length == s2.length
1 <= s1.length <= 30
s1 和 s2 由小写英文字母组成
【分析】
dp难呀
话不多说,先上题解
方法一:暴力递归(即官方解法python代码
class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
@cache
def dfs(i1: int, i2: int, length: int) -> bool:
"""
第一个字符串从 i1 开始,第二个字符串从 i2 开始,子串的长度为 length,是否和谐
""" # 判断两个子串是否相等
if s1[i1:i1+length] == s2[i2:i2+length]:
return True # 判断是否存在字符 c 在两个子串中出现的次数不同
if Counter(s1[i1:i1+length]) != Counter(s2[i2:i2+length]):
return False # 枚举分割位置
for i in range(1, length):
# 不交换的情况
if dfs(i1, i2, i) and dfs(i1 + i, i2 + i, length - i):
return True
# 交换的情况
if dfs(i1, i2 + length - i, i) and dfs(i1 + i, i2, length - i):
return True return False ans = dfs(0, 0, len(s1))
dfs.cache_clear()
return ans
方法二:记忆化搜索(即预定义数组,递归过程中直接调用已计算值,思想类似于预处理,dp
class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
demo = [[[None for i in range(31)] for i in range(31)] for i in range(31)]
@cache
def dfs(i1: int, i2: int, length: int) -> bool:
if demo[i1][i2][length] != None:
return demo[i1][i2][length]
"""
第一个字符串从 i1 开始,第二个字符串从 i2 开始,子串的长度为 length,是否和谐
""" # 判断两个子串是否相等
if s1[i1:i1+length] == s2[i2:i2+length]:
demo[i1][i2][length] = True
return True # 枚举分割位置
for i in range(1, length):
# 不交换的情况
if dfs(i1, i2, i) and dfs(i1 + i, i2 + i, length - i):
demo[i1][i2][length] = True
return True
# 交换的情况
if dfs(i1, i2 + length - i, i) and dfs(i1 + i, i2, length - i):
demo[i1][i2][length] = True
return True
demo[i1][i2][length] = False
return False ans = dfs(0, 0, len(s1))
dfs.cache_clear()
return ans
方法三:区间dp
// 对应了「s1 的 [0,i) & [i,n)」匹配「s2 的 [0,i) & [i,n)」
if (dfs(i, j, k) && dfs(i + k, j + k, len - k)) {
cache[i][j][len] = Y;
return true;
}
// 对应了「s1 的 [0,i) & [i,n)」匹配「s2 的 [n-i,n) & [0,n-i)」
if (dfs(i, j + len - k, k) && dfs(i + k, j, len - k)) {
cache[i][j][len] = Y;
return true;
}
class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
if s1 == s2:
return True
if len(s1) != len(s2):
return False
length = len(s1)
demo = [[[False for i in range(length+1)] for i in range(length)] for i in range(length)] for i in range(length):
for j in range(length):
demo[i][j][1] = s1[i] == s2[j] for l in range(2, length+1):
for i in range(length - l + 1):
for j in range(length - l + 1):
for k in range(1, l):
a = demo[i][j][k] and demo[i + k][j + k][l - k];
b = demo[i][j + l - k][k] and demo[i + k][j][l - k];
if (a or b):
demo[i][j][l] = True
return demo[0][0][length]
yysy,不知道为啥,后面两种
leetcode时间消耗还更大,估计是内存频繁创建demo数组原因
【python】Leetcode每日一题-扰乱字符串的更多相关文章
- 【python】Leetcode每日一题-前缀树(Trie)
[python]Leetcode每日一题-前缀树(Trie) [题目描述] Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的 ...
- 【python】Leetcode每日一题-最大数
[python]Leetcode每日一题-最大数 [题目描述] 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数. 注意:输出结果可能非常大,所以你需要返回一个 ...
- 【python】Leetcode每日一题-最长公共子序列
[python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...
- 【python】Leetcode每日一题-不同的子序列
[python]Leetcode每日一题-不同的子序列 [题目描述] 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数. 字符串的一个 子序列 是指,通过删除一些(也可以 ...
- 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素
[python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...
- 【python】Leetcode每日一题-删除有序数组中的重复项
[python]Leetcode每日一题-删除有序数组中的重复项 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现一次 ,返回删除后数组的新长度. 不要 ...
- 【python】Leetcode每日一题-存在重复元素3
[python]Leetcode每日一题-存在重复元素3 [题目描述] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] ...
- 【python】Leetcode每日一题-打家劫舍2
[python]Leetcode每日一题-打家劫舍2 [题目描述] 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋 ...
- 【python】Leetcode每日一题-二叉搜索树节点最小距离
[python]Leetcode每日一题-二叉搜索树节点最小距离 [题目描述] 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例1: 输入:root = [4 ...
随机推荐
- Docker 三剑客 到 k8s 介绍
一.Docker 三剑客 Docker-Compose Docker-Compose 是用来管理你的容器的,有点像一个容器的管家,想象一下当你的Docker中有成百上千的容器需要启动,如果一个一个的启 ...
- 翻译:《实用的Python编程》04_04_Defining_exceptions
目录 | 上一节 (4.3 特殊方法) | 下一节 (5 对象模型) 4.4 定义异常 用户可以通过类实现自定义异常: class NetworkError(Exception): pass **异常 ...
- golang实现已知三角形三点坐标,求三角形面积
代码如下: func GetTriangleAreaByVector(x vector.Vector3,y vector.Vector3,z vector.Vector3) float64 { //根 ...
- Flutter学习简记
StatefulWidget和StatelessWidget StatefulWidget : 具有可变状态的窗口部件,也就是你在使用应用的时候就可以随时变化,比如我们常见的进度条,随着进度不断变化. ...
- Spring Boot 自动装配原理
Spring Boot 自动装配原理 Spring Boot 在启动之前还有一系列的准备工作,比如:推断 web 应用类型,设置初始化器,设置监听器,启动各种监听器,准备环境,创建 applicati ...
- 五个问题,三大策略,手把手教你定制App性能监控方案
作者:友盟+U-APM团队 Why? 为什么要做应用性能监控? 首先,我们要知道应用性能监控具体指什么?以及目的: 监控是一套完整的"监视+报警"的系统.对于像我们这样的App开发 ...
- Java中HashMap的源码分析
先来回顾一下Map类中常用实现类的区别: HashMap:底层实现是哈希表+链表,在JDK8中,当链表长度大于8时转换为红黑树,线程不安全,效率高,允许key或value为null HashTable ...
- PTA 数组循环右移
6-2 数组循环右移 (20 分) 本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>)个整数,将每个整数循环向右移m(≥)个位置,即将a中的数据由(a0a1⋯ ...
- 生产中常用的du命令
1. 介绍 du是用来查看文件或目录所占用磁盘空间的大小 du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-size][--exc ...
- Java生鲜电商平台-API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)
Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...