87. 扰乱字符串

简介: 87. 扰乱字符串

前言

使用下面描述的算法可以扰乱字符串 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 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/scramble-string

暴力递归

样本对应模型
按第一刀的情况来分
在这里插入图片描述

定义函数f(s1,L1,R1, s2,L2,R2):
str1的L1-R1,对str2 L2-R2等长,看str1的L1~R1,对str2 L2~R2这一段是不是玄变字符串

base case
当你L1到R1上只有一个字符,
如果str1[L1]==str2[L2],返回true

普遍情况
枚举的方式是str1第一刀切哪儿了
1)第一刀0-0, 1-9
在这里插入图片描述

在这里插入图片描述
两种情况
1.两个字符串一一对应
2.str1前部分对于str2后部分,str1后部分对应str2前部分
即字符进行了变换

2)0-1,2-9
...
9)0-8,9-9

    public static boolean isScramble(String s1, String s2) {
        if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) {
            return false;
        }
        if (s1 == null && s2 == null) {
            return true;
        }
        if (s1.equals(s2)) {
            return true;
        }
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        if (!sameTypeSameNumber(str1, str2)) {
            return false;
        }
        return process0(str1, 0, str1.length - 1, str2, 0, str2.length - 1);
    }

    // str1[L1...R1] str2[L2...R2] 是否互为玄变串
    // 一定保证这两段是等长的!
    public static boolean process(char[] str1, int L1, int R1, char[] str2, int L2, int R2) {
        if (L1 == R1) {
            return str1[L1] == str2[L2];
        }
        for (int leftEnd = L1; leftEnd < R1; leftEnd++) {
            boolean p1 = process0(str1, L1, leftEnd, str2, L2, L2 + leftEnd - L1)
                    && process0(str1, leftEnd + 1, R1, str2, L2 + leftEnd - L1 + 1, R2);
            boolean p2 = process0(str1, L1, leftEnd, str2, R2 - (leftEnd - L1), R2)
                    && process0(str1, leftEnd + 1, R1, str2, L2, R2 - (leftEnd - L1) - 1);
            if (p1 || p2) {
                return true;
            }
        }
        return false;
    }

二、记忆化搜索

如果我们使用四维表记录的话,那就太浪费空间了
我们可以减少一维,使用三维表
递归参数设置为

process(char[] str1,int L1,char[] str2,int L2,int size,int[][][] dp)

用size可以推出R1和R2
这样就可以节省空间了

class Solution {
    public boolean isScramble(String s1, String s2) {
        if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) {
            return false;
        }
        if (s1 == null && s2 == null) {
            return true;
        }
        if (s1.equals(s2)) {
            return true;
        }
        char[] str1=s1.toCharArray();
        char[] str2=s2.toCharArray();
        int size=str1.length;
        int[][][] dp=new int[size][size][size+1];
        return process(str1,0,str2,0,size,dp);
    }
    
    public boolean process(char[] str1,int L1,char[] str2,int L2,int size,int[][][] dp){
        if(dp[L1][L2][size]!=0){
            return dp[L1][L2][size]==1;
        }
        boolean ans = false;
        if(size==1){
           ans=str1[L1]==str2[L2];
        }else{
            for(int leftPart=1;leftPart<size;leftPart++){
                boolean p1=process(str1,L1,str2,L2,leftPart,dp)
                &&process(str1,L1+leftPart,str2,L2+leftPart,size-leftPart,dp);
                boolean p2=process(str1,L1,str2,L2+size-leftPart,leftPart,dp)&&
                process(str1,L1+leftPart,str2,L2,size-leftPart,dp);
                if(p1||p2){
                    ans=true;
                    break;
                }
            }
        }
        dp[L1][L2][size]=ans?1:-1;
        return ans;
    }
}
相关文章
|
8月前
50.编写程序,逆转字符串
50.编写程序,逆转字符串
51 0
|
索引
【Leetcode -383.赎金信 -387.字符串中的第一个唯一字符】
【Leetcode -383.赎金信 -387.字符串中的第一个唯一字符】
45 0
1446. 连续字符【我亦无他唯手熟尔】
1446. 连续字符【我亦无他唯手熟尔】
55 0
|
算法 Python
【完虐算法】「字符串-最长公共前缀」5种方法脑洞大开
最近在专题制作过程中遇到了**最长前缀公共子串**的问题,也是读者最近校招面试到的一个题目。为什么拿出这个来说呢? 可怕的是,他居然给了 5 种解题方法。 更可怕的是,因此他直接少了一轮面试,天哪!!
406 0
|
存储 算法 索引
438. 找到字符串中所有字母异位词【我亦无他唯手熟尔】
438. 找到字符串中所有字母异位词【我亦无他唯手熟尔】
66 0
|
算法 C语言
【基础算法】浅浅刷个小题 # 移动零 # 丢失的数字 # 转换成小写字母 # 和为零的N个不同整数 # 猜数字 #
【基础算法】浅浅刷个小题 # 移动零 # 丢失的数字 # 转换成小写字母 # 和为零的N个不同整数 # 猜数字 #
|
算法 测试技术
算法强化每日一题--字符串中找出连续最长的数字串
算法强化每日一题--字符串中找出连续最长的数字串
|
存储 数据可视化 算法
字符串之谜:如何找到出现频率最高的字符?
字符串之谜:如何找到出现频率最高的字符?
248 0
用C++实现字符的逆转
用C++实现字符的逆转
【基础算法】浅浅刷个小题 # 找不同 # 字符串中的单词数 # 重新排列字符串 #
【基础算法】浅浅刷个小题 # 找不同 # 字符串中的单词数 # 重新排列字符串 #