JAVA程序设计: 交错字符串(LeetCode:97)

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

示例 1:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true
示例 2:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出: false

方法一:简单的暴力回朔

class Solution {
	
	boolean flag=false;
	int len1,len2,len3;
	
    public boolean isInterleave(String s1, String s2, String s3) {
        
    	if(s3.length()!=s1.length()+s2.length())
    		return false;
    	
    	int[] nums=new int[26];
    	
    	for(int i=0;i<s3.length();i++)
    		nums[s3.charAt(i)-'a']++;
    	for(int i=0;i<s1.length();i++)
    			nums[s1.charAt(i)-'a']--;
    	for(int i=0;i<s2.length();i++)
    			nums[s2.charAt(i)-'a']--;
    	for(int i=0;i<26;i++)
    		if(nums[i]!=0)
    			return false;
    	
    	len1=s1.length();
    	len2=s2.length();
    	len3=len1+len2;
    	
    	dfs(s1,s2,s3,0,0,0);
    	
    	return flag;
    }
    
    private void dfs(String s1,String s2,String s3,int x,int y,int z)
    {
    	if(flag) return;
    	
    	if(z==len3)
    	{
    		flag=true;
    		return;
    	}
    	
    	if(x<len1 && s1.charAt(x)==s3.charAt(z))
    		dfs(s1,s2,s3,x+1,y,z+1);
    	if(y<len2 && s2.charAt(y)==s3.charAt(z))
    		dfs(s1,s2,s3,x,y+1,z+1);
    }
}

方法二:记忆化搜索,我们知道方法一中的回朔是存在很多冗余次数的回朔,一些可能的情况完全没有必要再遍历,因此我们可以开一个二维数组存一下已经得出答案的子串的情况。

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
    	
        int memo[][] =new int[s1.length()][s2.length()];
        
        for(int i=0;i<s1.length();i++)
        	for(int j=0;j<s2.length();j++)
        		memo[i][j]=-1;
        
        return dfs(s1,0,s2,0,s3,0,memo);
    	
    }
    
    private boolean dfs(String s1,int i,String s2,int j,String s3,int k,int[][] memo)
    {
    	if(i==s1.length())
    		return s2.substring(j).equals(s3.substring(k));
    	if(j==s2.length())
    		return s1.substring(i).equals(s3.substring(k));
    	
    	if(memo[i][j]>=0)
    		return memo[i][j]==1?true:false;
    	
    	boolean ans=false;
    	
    	if(s3.charAt(k)==s1.charAt(i) && dfs(s1,i+1,s2,j,s3,k+1,memo) || s3.charAt(k)==s2.charAt(j) && dfs(s1,i,s2,j+1,s3,k+1,memo))
    		ans=true;
    	
    	memo[i][j]=ans?1:0;
    	return ans;
    }
}

方法三:动态规划

前两种方法我们都是枚举以第一个串的i开头或者以第二个串的j开头组成的后缀串是否与第三个串的后缀相同,我们可以考虑第一个串以i结尾,第二个串以j结尾的串的前缀和第三个串以k为前缀的串是否匹配。

发现题解讲的非常好,因此我直接贴出截图:

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
    	
    	if(s3.length()!=s1.length()+s2.length())
    		return false;
    	
    	boolean[][] dp=new boolean[s1.length()+1][s2.length()+1];
    	
    	for(int i=0;i<=s1.length();i++)
    		for(int j=0;j<=s2.length();j++)
    		{
    			if(i+j==0)
    				dp[i][j]=true;
    			else if(i==0)
    				dp[i][j]=dp[i][j-1] && s2.charAt(j-1)==s3.charAt(i+j-1);
    			else if(j==0)
    				dp[i][j]=dp[i-1][j] && s1.charAt(i-1)==s3.charAt(i+j-1);
    			else
    				dp[i][j]=dp[i-1][j] && s1.charAt(i-1)==s3.charAt(i+j-1) || dp[i][j-1] && s2.charAt(j-1)==s3.charAt(i+j-1);
    		}
    	
    	return dp[s1.length()][s2.length()];
    	
    }
}

方法四:对于第三种方法我们可以做进一步的优化,将二维数组降到一维。

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
    	
    	if(s3.length()!=s1.length()+s2.length())
    		return false;
    	
    	boolean[] dp=new boolean[s2.length()+1];
    	
    	for(int i=0;i<=s1.length();i++)
    		for(int j=0;j<=s2.length();j++)
    		{
    			if(i+j==0)
    				dp[j]=true;
    			else if(i==0)
    				dp[j]=dp[j-1] && s2.charAt(j-1)==s3.charAt(i+j-1);
    			else if(j==0)
    				dp[j]=dp[j] && s1.charAt(i-1)==s3.charAt(i+j-1);
    			else
    				dp[j]=dp[j] && s1.charAt(i-1)==s3.charAt(i+j-1) || dp[j-1] && s2.charAt(j-1)==s3.charAt(i+j-1);
    		}
    	
    	return dp[s2.length()];
    	
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值