字符串拆开成两个_leetcode87_go_扰乱字符串

题目

给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。

下图是字符串 s1 = "great" 的一种可能的表示形式。

great

/

gr eat

/ /

g r e at

/

a t

在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。

例如,如果我们挑选非叶节点 "gr" ,交换它的两个子节点,将会产生扰乱字符串 "rgeat" 。

rgeat

/

rg eat

/ /

r g e at

/

a t

我们将 "rgeat” 称作 "great" 的一个扰乱字符串。

同样地,如果我们继续交换节点 "eat" 和 "at" 的子节点,将会产生另一个新的扰乱字符串 "rgtae" 。

rgtae

/

rg tae

/ /

r g ta e

/

t a

我们将 "rgtae” 称作 "great" 的一个扰乱字符串。

给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。

示例 1:输入: s1 = "great", s2 = "rgeat" 输出: true

示例 2:输入: s1 = "abcde", s2 = "caebd" 输出: false

解题思路分析

1、动态规划;时间复杂度O(n^4),空间复杂度O(n^3)

f0df89d85f3e633d39ea806ea2d27481.png
func isScramble(s1 string, s2 string) bool {n, m := len(s1), len(s2)if n != m {return false}// dp[i][j][l]:表示s1从i开始,s2从j开始长度为l的两个子字符串是扰乱dp := make([][][]bool, n+1)for i := 0; i <= n; i++ {dp[i] = make([][]bool, n+1)for j := 0; j <= n; j++ {dp[i][j] = make([]bool, n+1)}}// 单个字符for i := 0; i < n; i++ {for j := 0; j < n; j++ {dp[i][j][1] = s1[i] == s2[j]}}for k := 2; k <= n; k++ { // 枚举长度: 2-nfor i := 0; i <= n-k; i++ { // s1起点for j := 0; j <= n-k; j++ { // s2起点dp[i][j][k] = false// 长度为w,分为两部分,其中最少是1for w := 1; w <= k-1; w++ {// 划分不交换:S1->T1, S2->T2// 划分交换: S1->T2, S2->T1if (dp[i][j][w] == true && dp[i+w][j+w][k-w] == true) ||(dp[i][j+k-w][w] == true && dp[i+w][j][k-w] == true) {dp[i][j][k] = true}}}}}return dp[0][0][n]}

2、递归;时间复杂度O(5^n),空间复杂度O(n)

func isScramble(s1 string, s2 string) bool {return dfs([]byte(s1), []byte(s2))}func dfs(arr1, arr2 []byte) bool {if compare(arr1, arr2) == false {return false}if len(arr1) <= 2 {return (len(arr1) == 2 && ((arr1[0] == arr2[0] && arr1[1] == arr2[1]) ||(arr1[0] == arr2[1] && arr1[1] == arr2[0]))) ||(len(arr1) == 1 && arr1[0] == arr2[0])}for i := 1; i < len(arr1); i++ {leftA, rightA := arr1[:i], arr1[i:]leftB, rightB := arr2[:i], arr2[i:]LB, RB := arr2[len(arr1)-i:], arr2[:len(arr1)-i]if (dfs(leftA, leftB) && dfs(rightA, rightB)) || (dfs(leftA, LB) && dfs(rightA, RB)) {return true}}return false}func compare(arr1, arr2 []byte) bool {if len(arr1) != len(arr2) {return false}arrA := make([]byte, 26)arrB := make([]byte, 26)for i := 0; i < len(arr1); i++ {arrA[arr1[i]-'a']++arrB[arr2[i]-'a']++}for i := 0; i < len(arrA); i++ {if arrA[i] != arrB[i] {return false}}return true}

总结

Hard题目,考察字符串动态规划解法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值