一起刷LeetCode——扰乱字符串(递归)

66 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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;
};

递归

  • 在定义扰乱字符串的时候,整个的描述比较符合递归模型,因此也可以使用递归来解决这个问题

总结

  • 很多情况下,题目描述的很复杂,从最初的参数和最终结果上来看,可以把中间过程简化,只有一部分的操作保留在了结果中
  • 今天也是有收获的一天