【问题标题】:Interleaving Strings Recursive and Top Down Approach交织字符串递归和自顶向下方法
【发布时间】:2021-08-15 09:13:43
【问题描述】:

我是数据结构和算法的初学者。我正在解决这个我卡住的问题。我相信我的方法是正确的,但我在 LeetCode 上提交解决方案时收到了WA

问题Link - 给定三个字符串 s1、s2 和 s3,判断 s3 是否由 s1 和 s2 交织而成。

解决方法 - 我使用蛮力(递归方法),我使用三个指针,如果在其中任何一个中找到匹配项,则移动它们。这是我的方法(我不知道为什么会失败)-

public boolean isInterleave(String s1, String s2, String s3) {
    if(s1.length() + s2.length() != s3.length())
        return false;
    
    return isInterleave(s1, s2, s3, 0, 0, 0);
}

private boolean isInterleave(String s1, String s2, String s3, int i, int j, int k){
    if(i == s1.length() && j == s2.length() && k == s3.length())
        return true;
    
    if(i >= s1.length())
        return s2.charAt(j) == s3.charAt(k) ? isInterleave(s1, s2, s3, i, j + 1, k + 1): false;
    
    if(j >= s2.length())
        return s1.charAt(i) == s3.charAt(k) ? isInterleave(s1, s2, s3, i + 1, j, k + 1): false;
    
    if(s1.charAt(i) == s3.charAt(k) && s2.charAt(j) != s3.charAt(k))
        return isInterleave(s1, s2, s3, i + 1, j, k + 1);
    
    if(s1.charAt(i) != s3.charAt(k) && s2.charAt(j) == s3.charAt(k))
        return isInterleave(s1, s2, s3, i, j + 1, k + 1);
    
    if(s1.charAt(i) == s3.charAt(k) && s2.charAt(j) == s3.charAt(k))
        return isInterleave(s1, s2, s3, i + 1, j, k + 1) || isInterleave(s2, s2, s3, i, j + 1, k + 1);
    
    return false;
}

请告诉我我的错误。

此外,我相信这个解决方案的时间复杂度是O(2^(M + N)),其中 M 和 N 是字符串长度。我想使用记忆化(自上而下的方法),但我发现很难想到它,因为解决方案需要布尔值。谁能告诉我如何处理这个问题?

【问题讨论】:

  • 倒数第二行错误为isInterleave(s2, s2, s3, i, j + 1, k + 1)。应该是isInterleave(s1, s2, s3, i, j + 1, k + 1)

标签: java string algorithm recursion


【解决方案1】:

只要任何字符与最终字符串的当前字符匹配,您就必须调用该函数。所以你可以做的是简单地获取一个布尔变量并更新它(通过使用你得到的递归结果执行OR

此外,您可以通过简单地比较其余字符串,避免在到达任何字符串末尾时进行不必要的调用。

更新的解决方案 -

public boolean isInterleave(String s1, String s2, String s3) {
    if(s1.length() + s2.length() != s3.length())
        return false;
    
    return isInterleave(s1, s2, s3, 0, 0, 0);
}

private boolean isInterleave(String s1, String s2, String s3, int i, int j, int k){
    if(k == s3.length())
        return i == s1.length() && j == s2.length() ? true : false;
    
    if(i == s1.length())
        return (s2.substring(j)).equals(s3.substring(k));
    
    if(j == s2.length())
        return (s1.substring(i)).equals(s3.substring(k));
    
    boolean cr = false;
    
    if(s1.charAt(i) == s3.charAt(k))
        cr = cr || isInterleave(s1, s2, s3, i + 1, j, k + 1);
    
    if(s2.charAt(j) == s3.charAt(k))
        cr = cr || isInterleave(s1, s2, s3, i, j + 1, k + 1);
    
    return cr;
}

现在讨论自上而下的方法。显然存在重叠的子问题。所以你可以做的是简单地使用HashMap 来存储当前子问题的答案。 [如何 ?那么你可以创建一个String类型的Key,将i、j和k连接起来,并存储相应的堆栈结果。]

方法-

public boolean isInterleave(String s1, String s2, String s3) {
    if(s1.length() + s2.length() != s3.length())
        return false;
    
    map = new HashMap<>();
    
    return isInterleave(s1, s2, s3, 0, 0, 0);
}

private Map<String, Boolean> map;

private boolean isInterleave(String s1, String s2, String s3, int i, int j, int k){
    if(k == s3.length())
        return i == s1.length() && j == s2.length() ? true : false;
    
    if(i == s1.length())
        return (s2.substring(j)).equals(s3.substring(k));
    
    if(j == s2.length())
        return (s1.substring(i)).equals(s3.substring(k));
    
    String key = i + "*" + j + "*" + k;
    if(map.containsKey(key))
        return map.get(key);
    
    boolean cr = false;
    
    if(s1.charAt(i) == s3.charAt(k))
        cr = cr || isInterleave(s1, s2, s3, i + 1, j, k + 1);
    
    if(s2.charAt(j) == s3.charAt(k))
        cr = cr || isInterleave(s1, s2, s3, i, j + 1, k + 1);
    
    map.put(key, cr);
    return cr;
}

【讨论】:

  • 您能解释一下为什么@Sherlock 代码没有给出正确的输出吗?
猜你喜欢
  • 2020-01-06
  • 2019-05-10
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
相关资源
最近更新 更多