class Solution {
public:
bool isScramble(string s1, string s2) {
}
};
87. 扰乱字符串
使用下面描述的算法可以扰乱字符串s
得到字符串 t
:
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
由小写英文字母组成原站题解
golang 解法, 执行用时: 4 ms, 内存消耗: 3.9 MB, 提交时间: 2023-09-04 11:22:15
func isScramble(s1, s2 string) bool { n := len(s1) dp := make([][][]int8, n) for i := range dp { dp[i] = make([][]int8, n) for j := range dp[i] { dp[i][j] = make([]int8, n+1) for k := range dp[i][j] { dp[i][j][k] = -1 } } } // 第一个字符串从 i1 开始,第二个字符串从 i2 开始,子串的长度为 length // 和谐返回 1,不和谐返回 0 var dfs func(i1, i2, length int) int8 dfs = func(i1, i2, length int) (res int8) { d := &dp[i1][i2][length] if *d != -1 { return *d } defer func() { *d = res }() // 判断两个子串是否相等 x, y := s1[i1:i1+length], s2[i2:i2+length] if x == y { return 1 } // 判断是否存在字符 c 在两个子串中出现的次数不同 freq := [26]int{} for i, ch := range x { freq[ch-'a']++ freq[y[i]-'a']-- } for _, f := range freq[:] { if f != 0 { return 0 } } // 枚举分割位置 for i := 1; i < length; i++ { // 不交换的情况 if dfs(i1, i2, i) == 1 && dfs(i1+i, i2+i, length-i) == 1 { return 1 } // 交换的情况 if dfs(i1, i2+length-i, i) == 1 && dfs(i1+i, i2, length-i) == 1 { return 1 } } return 0 } return dfs(0, 0, n) == 1 }
python3 解法, 执行用时: 88 ms, 内存消耗: 16.2 MB, 提交时间: 2023-09-04 11:21:38
# dp 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