LeetCode97题 交错字符串

模拟自己正常的思维过程

选取 s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac” 为样例

  1. 选s3的第1个a, 然后分别拿s1的第1个和s2的第1个做比较,发现s1的第1个匹配。

  2. 选s3的第2个a, 然后分别拿s1的第2个和s2的第1个做比较,发现s1的第2个匹配。这时候幡然醒悟,需要加两个指针指向iS1 和iS2的当前位置。

  3. 所以重来: 选s3的第1个a, 然后分别拿s1的第1个和s2的第1个做比较,发现s1的第1个匹配。iS1++;

  4. 选s3的第2个a, 然后分别拿s1的第2个和s2的第1个做比较,发现s1的第2个匹配。iS1++;

  5. 选第s3的第n个 (0<n<=s1.length()),如果s1.charAt(iS1)匹配那就去选s3的n+1个继续匹配并且iS1+1。如果s2.charAt(iS2)匹配那就去选s3的n+1个继续匹配并且iS2+1。转换成代码如下

            if(iS2<s2.length()&&s2.charAt(iS2)==s3.charAt(iS2+iS3)){
                dp(s2, s3, s1, iS2+1, iS3);
            }
    
            if(iS1<s1.length()&&s1.charAt(iS1)==s3.charAt(iS2+iS3)){
                dp(s2, s3, s1, iS2, iS3+1);
            }
    
那么整体的暴力递归代码如下
    public boolean  dp(String s2,String s3,String s1,int iS2,int iS1){
        if(iS2+iS1==s3.length()){
            return true;
        }
        boolean t1=false;
        boolean t2=false;
        if(iS2<s2.length()&&s2.charAt(iS2)==s1.charAt(iS2+iS1)){
            t1=dp(s2, s3, s1, iS2+1, iS1);
        }

        if(iS1<s1.length()&&s1.charAt(iS1)==s1.charAt(iS2+iS1)){
            t2=dp(s2, s3, s1, iS2, iS1+1);
        }
        return t1||t2;

    }
加上记忆化搜索进行优化
    //visited 有三种值,0代表没访问 1代表访问,但是为false ,2代表访问并且为true
    public boolean  dp(String s2,String s3,String s1,int iS2,int iS1,int[][] visited){
        if(iS2+iS1==s3.length()){
            return true;
        }
        boolean t1=false;
        boolean t2=false;
        if(iS2<s2.length()&&s2.charAt(iS2)==s1.charAt(iS2+iS1)){
            if(visited[iS2+1][iS1]==0){
                t1=dp(s2, s3, s1, iS2+1, iS1,visited);
                visited[iS2+1][iS1]= t1==true?2:1;
            }else {
                t1=visited[iS2+1][iS1]==1?false:true;
            }

        }

        if(iS1<s1.length()&&s1.charAt(iS1)==s1.charAt(iS2+iS1)){
            if(visited[iS2][iS1+1]==0){
                t2=dp(s2, s3, s1, iS2, iS1+1,visited);
                visited[iS2][iS1+1]= t2==true?2:1;
            }else {
                t2=visited[iS2][iS1+1]==1?false:true;
            }
            
        }
        return t1||t2;

    }

就可以过leetcode了

动态规划

根据暴力递归的样式,我是很快的反应出来了跟机器人类似(机器人每次只能走下或者右)。

正常的动态规划的步骤

  1. 确定状态:dp(i,j) s3的前i+j个元素是否可以交错而成.(s1的前i个元素和s2的前j个元素)

  2. 递推公式: dp(i,j)=dp(i-1,j)||dp(i,j-1)

  3. 基础case:d(0,0)=true

  4. 代码

        public boolean isInterleave(String s1, String s2, String s3) {
            if(s3.length()!=s2.length()+s1.length()){
                return false;
            }
            boolean[][] dp=new boolean[s1.length()+1][s2.length()+1];
    
            for (int i=0;i<s1.length()+1;i++){
                for (int j=0;j<s2.length()+1;j++){
                    if(i==0&&j==0){
                        dp[i][j]=true;
                        continue;
                    }
    
                    if(i>0&&s1.charAt(i-1)==s3.charAt(i+j-1)){
                        if(dp[i-1][j]){
                            dp[i][j]=true;
                        }
                    }
    
                    if(j>0&&s2.charAt(j-1)==s3.charAt(i+j-1)){
                        if(dp[i][j-1]){
                            dp[i][j]=true;
                        }
                    }
                }
            }
            return dp[s1.length()][s2.length()];
    
        }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值