leetcode 87. Scramble String(扰乱字符串)

在这里插入图片描述

scramble(字符串s) 算法:
s长度为1时结束。
s可以拆分成2部分x和y,s=x+y,
这两部分可以交换,也可以不交换,即 s = x+y 或 s = y+x.
上面scramble还会递归作用于x 和 y.

给出相同长度的字符串s1, s2, 问s2是否可通过scramble(s1)获得。

思路:

假设s1和s2的长度是n.

在scramble算法中,第1,字符串可以拆分成两部分
那么可以拆分的点可以在任意下标处,
所以需要遍历s1的所有下标。
假设遍历下标为 i 时,s 拆分成 0 ~ i 和 i+1 ~ n-1两段。所以 i : 0 ~ n-2 (不是n-1 !)

第2,拆分的两部分 可交换可不交换
假设在 i 处把s1分成两部分: s1[0 ~ i] 和 s1[i+1 ~ n-1] ,
如果不交换,需要进一步scramble s1[0 ~ i] 和 s2[0 ~ i], s1[i+1 ~ n-1] 和 s2[i+1 ~ n-1].
如果交换,需要进一步scramble s1[0 ~ i] 和 s2[i ~ n-1], s1[i+1 ~ n-1] 和 s2[0 ~ i-1].

同时,我们观察到,
s1能scramble成s2的前提是 它们的字母必须是一样的(不管顺序)。
因为scramble只负责拆分和交换,并不会改变字母,
如果字母不一样,则s1 scamble不成s2的.

所以可以用一个长度为26的数组统计每个字母出现的次数,
因为涉及到交换和不交换,
所以分别用一个cnt统计s1[0 ~ i]的字母,
cntF统计s2[0 ~ i]的字母,cntB统计s2[i+1 ~ n-1]的字母。
字母个数相同时,再进行scamble算法。

两个字符串相等时结束
已经判断过的,用一个map保存起来,再遇到同样的s1和s2, 直接取结果。

注意s必须是拆分成2部分,因此 i < n-1, 而不是 i < n,如果 i = n-1, 会相当于只拆分成一部分(即s1本身,会陷入无限循环)。

class Solution {
    HashMap<String, Boolean> map = new HashMap<>();
    
    public boolean isScramble(String s1, String s2) {
        String s = s1 + s2;
        //相当于DP,记录已经判断过的s1和s2
        if(!map.containsKey(s)) map.put(s, helper(s1, s2));
        return map.get(s);    
    }

    boolean helper(String s1, String s2) {
        if(s1.equals(s2)) return true;

        int[] cnt = new int[26];  //s1从前往后字母计数
        int[] cntF = new int[26]; //s2从前往后字母计数,cntForward
        int[] cntB = new int[26]; //s2从后往前字母计数,cntBackward

        for(int i = 0; i < s1.length()-1; i++) {  //遍历所有的分割点
            int j = s2.length()-1-i;
            cnt[s1.charAt(i)-'a']++;   //统计s1的0~i段字母个数
            cntF[s2.charAt(i)-'a']++;  //统计s2的0~i段(前半段)字母个数
            cntB[s2.charAt(j)-'a']++;  //统计s2的i~n-1段(后半段)字母个数

            if(Arrays.equals(cnt, cntF)) {  //s2的0~i段与s1的0~i段是否字母个数一致(相当于不swap)
                if(isScramble(s1.substring(0,i+1), s2.substring(0,i+1)) &&
                isScramble(s1.substring(i+1), s2.substring(i+1))) return true;
            }
            //不要用else if!不然会漏掉交换后的验证
            if(Arrays.equals(cnt, cntB)){  //s2的i~n-1段与s1的0~i段是否字母个数一致(相当于swap)
                if(isScramble(s1.substring(0,i+1), s2.substring(j)) && 
                isScramble(s1.substring(i+1), s2.substring(0,j))) return true;
            }
        }
        return false;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/5698.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WTW-16P 应用电路

1、WTW-16P 按键控制 PWM 输出应用电路 软件设置&#xff1a; 按键控制模式。 I/O 口定义&#xff1a; 选取 I/O 口 P00、P01、P02、P03 作为触发口&#xff0c;在编辑 WT588D 语音工程时&#xff0c;把触发口的按键定义为可触发播放的触发方式&#xff0c;就可进行工作。 BUS…

如何提高网站安全防护?

网站的安全问题一直是很多运维人员的心头大患&#xff0c;一个网站的安全性如果出现问题&#xff0c;那么后续的一系列潜在危害都会起到连锁反应。就好像网站被挂马&#xff0c;容易遭受恶意请求呀&#xff0c;数据泄露等等都会成为杀死网站的凶手。 1、让服务器有一个安全稳定…

百度双塔召回引擎MOBIUS

1. 概述 对于一个搜索或者推荐系统来说&#xff0c;分阶段的设计都是当下的一个标配&#xff0c;主要是为了平衡效率和效果&#xff0c;在百度的广告系统中&#xff0c;也是分成了如下的三层结构&#xff1a; 最上层的Matching阶段负责从全库中找到与query相关的候选集&#x…

KD2511N系列微电阻测试仪

一、产品概述 KD2511N系列微电阻测试仪是一款对变压器、电机、开关、继电器、接插件等各类直流电阻进行测试的仪器。其基本测试精度最高可达 0.05%&#xff0c;并具有较高的测量速度。 KD2511N微电阻测试仪使用了高精度恒流流经被测件以及四端测量&#xff0c;有效的消除了 引线…

Kafka 如何保证消息的消费顺序

文章目录先直接给出答案吧。在集群或者多partition下无法保障完全顺序消费&#xff0c;但是可以保障分区顺序消费。具体下面讲解。我们在使用消息队列的过程中经常有业务场景需要严格保证消息的消费顺序&#xff0c;比如我们同时发了 2 个消息&#xff0c;这 2 个消息对应的操作…

蓝桥杯——根据手册写底层

一、 DS18B20温度传感器 1.官方所给源码 /* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础&#xff0c;根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求&#xff0c;进行代码…

ssm入门

文章目录1.介绍ssm2.Spring篇基础内容&#x1fa85;什么是IOC&#xff08;控制反转&#xff09;Spring和IOC之间的关系IOC容器的作用以及内部存放IoC入门案例&#x1f4ec;DI&#xff08;Dependency Injection&#xff09;依赖注入依赖注入的概念IOC容器中哪些bean之间要建立依…

函数微分和导数的定义

1.我们先来看可导的定义&#xff1a; 相信这个大家都看的懂。 2.接下来我们看可微的定义&#xff1a; 你们有没用想过为什么会有可微&#xff0c;他是用来干什么的&#xff0c;我们接下来看下面这张图&#xff0c;特别是结合图2-11来说&#xff0c; 我们可以看到书上说可微是在…

【day2】Android Jetpack Compose环境搭建

【day2】Android Jetpack Compose环境搭建 以下是适用于 Jetpack Compose 的环境要求&#xff1a; Android Studio 版本&#xff1a;4.2 Canary 15 或更高版本Gradle 版本&#xff1a;7.0.0-beta02 或更高版本Android 插件版本&#xff1a;4.2.0-beta15 或更高版本Kotlin 版本…

MySQL 幻读问题

承接上文MySQL多版本并发控制MVCC实现原理 幻读现象 因为在RR&#xff08;可重复读&#xff09;隔离级别里&#xff0c;事务1的第二次查询没有生成新的readview&#xff0c;而是用的第一次查询时生成的readview&#xff0c;所以第二次查询返回2条数据&#xff0c;而不是3条数据…

看过来,这里有JavaScript技术干货?

今天是一篇正经的技术分享&#xff0c;针对JavaScript技能的十来个专业小技巧&#xff0c;如果你想提升一下JS方面的能力成为一个更好的前端开发人员&#xff0c;那么就可以接着看下去哦。 1、使用逻辑运算符进行短路评估 您可以使用逻辑运算符进行短路评估&#xff0c;方法是…

云边协同与人工智能AI的深度融合(云端训练、边端推理)

在面向物联网、大流量等场景下&#xff0c;为了满足更广连接、更低时延、更好控制等需求&#xff0c;云计算在向一种更加全局化的分布式节点组合形态进阶&#xff0c;边缘计算是其向边缘侧分布式拓展的新触角。 以物联网场景举例&#xff0c;设备产生大量数据&#xff0c;上传到…

都2023了,学习自动化测试还有必要么?会不会浪费我时间

最近收到不少小伙伴私信提问&#xff0c;其中问得比较多的就是“学习自动化测试有那么重要吗&#xff1f;”。 我的回答是肯定的——很重要。 相信不少同学都有诸如此类的疑问&#xff0c;例如&#xff1a;“日常工作中好像用不上自动化&#xff1f;”、“手工点点点好像也可…

【从零开始学习 UVM】9.1、UVM Config DB —— UVM Resource database 资源库详解

文章目录 resource 是一个参数化的容器,可以保存任意数据。资源可用于配置组件、为序列提供数据或在TestBench不同部分之间启用信息共享。它们使用作用域信息(scope)存储,因此其可见性可以限制在TestBench的某些部分中。您可以将任何数据类型放入资源数据库中,并使另一个组…

若依后端管理系统学习日志

文章目录遇到的问题1. 自定义模块404解决方案1. 自定义后台异常返回2. 添加导入按钮3. 树形列表搜索遇到的问题 1. 自定义模块404 idea没有报错&#xff0c;但是点击进去页面显示404。 F12查看错误信息&#xff0c;原来是访问后端controller接口没有成功&#xff0c;找不到导…

上传文件—ajax

目录 一、上传图片文件 1.写基本html 完成页面主框架 2.script部分 2-0 主框架 上传文件按钮被点击触发事件 2-1验证使得否选择文件 2-2 介绍 FormData 2-3 监听onreadystatechange事件 小结 二、实现上传文件进度条 1. 在bootstrap找进度条组件 2.script 完成进度条算法…

Java锁深入理解2——ReentrantLock

前言 本篇博客是《Java锁深入理解》系列博客的第二篇&#xff0c;建议依次阅读。 各篇博客链接如下&#xff1a; Java锁深入理解1——概述及总结 Java锁深入理解2——ReentrantLock Java锁深入理解3——synchronized Java锁深入理解4——ReentrantLock VS synchronized Java锁…

QT Qwidget 事件处理机制

qlineEdit Qt事件处理是指在Qt应用程序中处理各种事件的过程。事件是指在应用程序中发生的各种操作&#xff0c;例如按键、鼠标点击、窗口移动等。Qt提供了一个事件处理机制&#xff0c;使得开发者可以对这些事件进行处理&#xff0c;以实现应用程序的各种功能。 Qt中的事件处…

CMake设置Visual Studio工程的调试环境变量和工作目录cwd的方法

1、设置在Visual Studio中调试的环境变量&#xff0c;此设置仅仅在VS中点击那个绿色三角运行时有效&#xff0c;与你直接双击打开exe文件运行无关&#xff0c;有效避免多版本动态库全部写入系统环境变量的污染问题&#xff1b; # Visual Studio中调试依赖的独立环境变量 set_p…

代码随想录算法训练营第五十天| ● 309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费 ●总结

309.最佳买卖股票时机含冷冻期 看完题后的思路 dp[i][] 0: 第i天不持有股票的最大利润 1: 持有 递推公式 dp[i][0]max(第i-1天不持有,第i-1天持有,在第i天卖了) dp[i][1]max(第i-1天持有, 第i-2天不持有,第i天持有) 初始化 dp[0][0]0; dp[0][1]-price[i]; dp[1][0]max(x,x) d…