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;
    }
}
相关文章
|
数据采集 Java 机器人
根据正则表达式截取字串符,这个办法打败99%程序员
作为一名程序员,常常会在以下情况下使用函数功能根据正则表达式截取字符串:
|
索引
【Leetcode -383.赎金信 -387.字符串中的第一个唯一字符】
【Leetcode -383.赎金信 -387.字符串中的第一个唯一字符】
41 0
|
存储 算法 索引
【每日挠头算法题(3)】字符串解码|数组中重复的数字
【每日挠头算法题(3)】字符串解码|数组中重复的数字
|
存储 算法
【每日挠头算法题(5)】重新格式化字符串|压缩字符串
【每日挠头算法题(5)】重新格式化字符串|压缩字符串
|
算法 Python
【完虐算法】「字符串-最长公共前缀」5种方法脑洞大开
最近在专题制作过程中遇到了**最长前缀公共子串**的问题,也是读者最近校招面试到的一个题目。为什么拿出这个来说呢? 可怕的是,他居然给了 5 种解题方法。 更可怕的是,因此他直接少了一轮面试,天哪!!
393 0
|
存储 数据可视化 算法
字符串之谜:如何找到出现频率最高的字符?
字符串之谜:如何找到出现频率最高的字符?
233 0
掉入陷阱的数字
掉入陷阱的数字
88 0
|
Python Windows
【一日一技】揭秘字符串的两副“面孔”
【一日一技】揭秘字符串的两副“面孔”
64 0
|
算法 Java
【算法】缺失的第一个正数,俄罗斯套娃信封问题
1.缺失的第一个正数 2.俄罗斯套娃信封问题
111 10
亲身经历:如何判断一个字符在a/z之前?
亲身经历:如何判断一个字符在a/z之前?
66 0