给定 2 个字符串和整数 k,以 k 步将一个字符串转换为另一个字符串

Posted

技术标签:

【中文标题】给定 2 个字符串和整数 k,以 k 步将一个字符串转换为另一个字符串【英文标题】:Given 2 strings and integer k, convert one string into another in exactly k steps 【发布时间】:2020-05-17 14:49:30 【问题描述】:

我正在解决“HackerRank”页面上的一个问题,特别是名为“追加和删除”的问题,但我无法使所有案例都正确。

https://www.hackerrank.com/challenges/append-and-delete/problem

"你有一串小写英文字母。你可以 对字符串执行两种类型的操作:

在字符串末尾附加一个小写英文字母。 删除字符串中的最后一个字符。执行此操作 空字符串导致空字符串。给定一个整数, 和 两个字符串,and ,确定是否可以转换为 by 在 上执行上述操作。如果它是可能的, 打印是的。否则,打印编号。

例如,字符串和 .我们的移动次数, .要转换为 ,我们 首先删除移动中的所有角色。接下来我们添加每个 字符的顺序。在移动中,您将拥有匹配的 细绳。如果有更多可用的动作,他们本来可以 通过对空字符串执行多次删除来消除。如果 有少于移动,我们不会成功地创造 新字符串。

功能说明

在下面的编辑器中完成 appendAndDelete 功能。这应该 返回一个字符串,是或否。

appendAndDelete 具有以下参数:

s:初始字符串 t:所需字符串 k:整数 表示操作数”。

int cont = 0;
        int limite = 0;


        if (s.length() < t.length())
            limite += s.length();
         else if (s.length() >= t.length())
            limite += t.length();
        

        for (int i = 0; i < limite; i++)

            if (s.charAt(i) != t.charAt(i))

                cont += 2;

            

        

        int diferen = 0;

        if (s.length() != t.length())

            diferen += (Math.abs(t.length() - s.length()));

         

        cont += diferen;

        if(cont <= k)

            return "Yes";

         else 
            return "No";
        

【问题讨论】:

【参考方案1】:

简介

要发现代码中的问题,让我们对其进行简化。

简化limite计算

要计算limite 值,您可以使用if/else 块,如下所示:

if (s.length() < t.length())
    limite += s.length();
 else if (s.length() >= t.length())
    limite += t.length();

但是,由于您的 limite 在此块之前始终是 0 并且您正在寻找的是最短字符串的长度,您可以简单地将其替换为:

int limite = Math.min(s.length(), t.length());

简化diferen计算

同样,您不需要任何if 块来计算您的diferen - 如果两个字符串的长度相同,那么diferen 就是0,这就是Math.abs(t.length() - s.length()) 也会产生的结果。

所以,不要这样:

int diferen = 0;
if (s.length() != t.length()) 
    diferen += (Math.abs(t.length() - s.length()));

您可以简单地使用单线:

int diferen = (Math.abs(t.length() - s.length()));

更好的变量名

diferencontlimite 这样的变量名称令人困惑。相反,您可以将这些变量重命名为 absLengthDifferenceoperationCountcommonLength

您的简化代码

static String appendAndDelete(String s, String t, int k) 
    int operationCount = 0;

    int shorterStringLength = Math.min(s.length(), t.length());

    for (int i = 0; i < commonLength; i++) 
        if (s.charAt(i) != t.charAt(i)) 
            operationCount += 2;
        
    

    int absLengthDifference = (Math.abs(t.length() - s.length()));
    operationCount += absLengthDifference;

    if(operationCount <= k) 
        return "Yes";
     

    return "No";

发现逻辑错误

因此,根据简介中所做的修改,我们将找出程序产生错误结果的原因。

让我们考虑如下输入:

ab

bb

2

您的程序将对此作出肯定的判断,因为 operationCount 将是 2operationCount &lt;= 2。所以,这是不正确的,因为要在任务中使用操作将ab 转换为bb,我们必须执行以下操作:

'ab' -> 'a' |到达“a”的唯一方法是删除“b”

'a' -> '' |纠正“a”的唯一方法是先将其删除

'' -> 'b' |然后附加'b'

'b' -> 'bb' |最后,再次追加'b'

如您所见,我们需要4 操作才能达到预期的结果,而不是2。因此,下面的块是错误的:

for (int i = 0; i < commonLength; i++) 
    if (s.charAt(i) != t.charAt(i)) 
        operationCount += 2;
    

添加是不够的2。如果您发现不匹配,则必须从末尾删除所有字符才能找到它(如示例中所示)。

另外,if(operationCount &lt;= k) 是错误的,因为操作数必须正好是k

解决办法

    首先要意识到的是,如果k 大于或等于字符串长度的总和,那么答案是Yes。我们可以从原始字符串s 中删除所有字符,并继续从空字符串0 中删除一个字符或更多次,然后从目标字符串t 中追加字符。 否则,如果找到两个公共字符串的长度commonLength,那么我们可以在s.length() + t.length() - 2*commonLength步骤中将s转换为t。但是,由于显而易见的原因,该值 minOperationCount 不能大于 k。此外,如果小于k,则k - minOperationCount 必须是2 的倍数。如果不是,则可以完全按照k 步骤进行转换。

代码

// Complete the appendAndDelete function below.
static String appendAndDelete(String s, String t, int k) 
    int totalLength = s.length() + t.length();
    if (totalLength <= k) 
        return "Yes";
    

    int commonLength = 0;
    for (int i = 0; i <  Math.min(s.length(), t.length()); i++) 
        if (s.charAt(i) != t.charAt(i)) 
            break;
        
        commonLength++;
      
    int minOperationCount = totalLength - 2 * commonLength;

    if(minOperationCount <= k && ((k - minOperationCount) % 2 == 0)) 
        return "Yes";
     

    return "No";
  

【讨论】:

以上是关于给定 2 个字符串和整数 k,以 k 步将一个字符串转换为另一个字符串的主要内容,如果未能解决你的问题,请参考以下文章

leetcode541

贪心算法-移除K个数字

541-反转字符串 II

541-反转字符串 II

字符串问题----去掉字符串中连续出现K个0的子串

给定一个字符串数组,再给定整数k,请返回出现次数前k名的字符串和对应的次数