携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
扰乱字符串
给你两个 长度相等 的字符串
s1
和s2
,判断s2
是否是s1
的扰乱字符串。如果是,返回true
;否则,返回false
。
分析
- 判断是否是扰乱字符串的条件是以一个字符串作为标准,另一个字符串任意点分成两部分,随机变换,随机变换指的是要么交换,要么不交换,之后继续任意点分成两部分,随机交换,直到分成的两部分长度为1,在这一过程如果和标准的字符相同,那就是互相为扰乱字符串,如果没有,就不是扰乱字符串
直观分析
- 从任意点,每次分成两部分选择是否交换直至分成的两部分中有一个长度为1的字符串,都可以最终展示为对整个字符串分成两部分这两部分的交换
- 循环出一个随机一个位置i,把s1分成[start,i]和[i,end]两部分,与s2中的相同范围匹配,如果匹配就跳出循环返回true,如果不匹配,就把s2的两部分交换一下,把s2的两部分表示为[i+1,end]和[start,i]进行匹配,直到循环结束,如果没有匹配成功的,返回true
- 在递归的时候使用缓存来记录,减少相同字符串的处理次数
代码
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var isScramble = function(s1, s2) {
let cache={};
let res = false;
if(cache[s1+s2]!==undefined){
return cache[s1+s2];
}
if(cache[s2+s1]!==undefined){
return cache[s2+s1];
}
if(s1.length===1){
return s1===s2;
}
let s1FirstPart,s1SecondPart,s2FirstPart,s2SecondPart;
for(let i=0;i<s1.length-1;i++){
s1FirstPart = s1.substring(0,i+1);
s1SecondPart = s1.substring(i+1);
s2FirstPart = s2.substring(0,i+1);
s2SecondPart = s2.substring(i+1);
if(match(s1FirstPart,s2FirstPart) && match(s1SecondPart,s2SecondPart){
res=true;
break;
}
s2FirstPart = s2.substring(s2.length-1-i);
s2SecondPart = s2.substring(0,s2.length-1-i);
if(match(s1FirstPart,s2FirstPart) && match(s1SecondPart,s2SecondPart){
res=true;
break;
}
}
cache[s1+s2] = res;
cache[s2+s1] = res
return res;
};
递归
- 在定义扰乱字符串的时候,整个的描述比较符合递归模型,因此也可以使用递归来解决这个问题
总结
- 很多情况下,题目描述的很复杂,从最初的参数和最终结果上来看,可以把中间过程简化,只有一部分的操作保留在了结果中
- 今天也是有收获的一天