【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 ...
随机推荐
- linux下redis安装运行教程——redis系列
天没降大任于我,照样苦我心智,劳我筋骨. 安装运行的过程 由于官网太慢,csdn里的资源又要钱,所以呢,只能使用我自己本地以前下载的陈年..哦不,3.xredis安装包 资源已经放到百度云,需要的可以 ...
- 非对称加密--密钥交换算法DHCoder
/* * 密钥交换算法,即非对称加密算法 * */ public class DHCoder { //非对称加密算法 public static final Str ...
- JAVA面试核心知识点(一):计算机网络
一·计算机网络 1.1 网络基础知识 OSI 七层协议(制定标准使用的标准概念框架): 物理层(传递比特流0101)->数据链路层(将比特流转换为逻辑传输线路)->网络层(逻辑编址,分组传 ...
- frp穿透内网使用vsftpd服务
本篇文章将会介绍如何使用frp穿透内网以及如何在centos8环境下安装和使用vsftpd,最后在公网通过frp穿透内网使用ftp. 一.内网穿透神器frp frp 是一个专注于内网穿透的高性能的反向 ...
- java例题_07 字符串的处理
1 /*7 [程序 7 处理字符串] 2 题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 3 程分析:利用 while 语句,条件为输入的字符不为'\n'. 4 */ 5 6 ...
- PAT (Advanced Level) Practice 1002 A+B for Polynomials (25 分) 凌宸1642
PAT (Advanced Level) Practice 1002 A+B for Polynomials (25 分) 凌宸1642 题目描述: This time, you are suppos ...
- Oracle 存储结构
数据库是存储数据的容器,它的主要功能是保存和共享数据. oracle数据库的存储结构可以分为逻辑存储结构和物理存储结构,对于这两种存储结构,oracle是分别进行管理的. 逻辑存储结构:oracle内 ...
- [GDKOI2021] 提高组 Day 1 总结
[ G D K O I 2021 ] 提 高 组 D a y 1 总 结 [GDKOI2021]~~ 提高组~~ Day~1~~ 总结 [GDKOI2021] 提高组 Day ...
- [图论]最优布线问题:kruskal
最优布线问题 目录 最优布线问题 Description Input Output Sample Input Sample Output Hint 解析 代码 Description 学校有n台计算机 ...
- python进阶(7)--文件与异常
一.文件读取二.文件写入三.异常四.存储数据 ---------------------------------------分割线:正文-------------------------------- ...