【问题标题】:Perl Morgan and a String?Perl Morgan 和字符串?
【发布时间】:2016-02-09 23:35:39
【问题描述】:

我正在尝试解决hackerrank 上的this 问题:

所以问题是:

杰克和丹尼尔是朋友。他们都喜欢字母,尤其是大写字母。 他们正在从报纸上剪下大写字母,每个人都将自己的字母集存放在不同的堆栈中。 美好的一天,摩根拜访了杰克和丹尼尔。他看到了他们的收藏。摩根想知道由这两个集合组成的字典上最小的字符串是什么。当它在堆栈的顶部时,他可以从集合中取出一封信。 此外,Morgan 想使用男孩收藏中的所有字母。

这是我在 Perl 中的尝试:

#!/usr/bin/perl
use strict;
use warnings;
chomp(my $n=<>);
while($n>0){
    chomp(my $string1=<>);
    chomp(my $string2=<>);
    lexi($string1,$string2);
    $n--;
}
sub lexi{
   my($str1,$str2)=@_;
   my @str1=split(//,$str1);
   my @str2=split(//,$str2);
   my $final_string="";

   while(@str2 && @str1){
       my $st2=$str2[0];
       my $st1=$str1[0];
       if($st1 le $st2){
         $final_string.=$st1;
         shift @str1;
       }
       else{
          $final_string.=$st2;
          shift @str2;
       }
  }
  if(@str1){
       $final_string=$final_string.join('',@str1);
  }
  else{
       $final_string=$final_string.join('',@str2);
  }
  print $final_string,"\n";
}

示例输入:

2
JACK
DANIEL
ABACABA
ABACABA

第一行包含测试用例的数量,T。 接下来的每两行都有这样的格式:第一行包含字符串 A,第二行包含字符串 B。

样本输出:

DAJACKNIEL
AABABACABACABA

但是对于 示例测试用例,它给出了 正确的结果,而对于 其他测试用例给出了错误的结果 /em>。它给出错误结果的一种情况是

1
AABAC
AACAB

它输出AAAABACCAB 而不是AAAABACABC

我不知道算法出了什么问题,为什么它在其他测试用例中失败了?

更新:

根据@squeamishossifrage cmets 如果我添加

($str1,$str2)=sort{$a cmp $b}($str1,$str2);

无论用户输入如何,结果都相同,但测试用例仍然失败。

【问题讨论】:

  • 最好包含您要解决的问题的摘要 - 否则您的答案依赖于该链接,如果它消失了,这是个坏消息。
  • @Sobrique 添加了摘要和输入/输出。
  • 我没有时间找出问题所在,但是很容易找到代码失败的测试用例。例如,字符串AABACAACAB 会根据它们出现的顺序给出不同的结果。
  • 我不懂 Perl。您是比较整个剩余字符串还是仅比较当前字符?你绝对应该做前者。
  • @squeamishossifrage 当字符串中的两个字符相等时它会失败并且 它失败是因为它会根据用户输入从不同的字符串中删除字符,我不确定如果我应该从哪个字符串中删除字符他们是平等的

标签: string algorithm perl


【解决方案1】:

问题在于您对相等字符的处理。举个例子:

ACBA
BCAB

当面对两个相同的字符(在我的示例中为C)时,您天真地从第一个字符串中选择了一个,但这并不总是正确的。你需要向前看才能打破关系。您甚至可能需要向前看许多字符。在这种情况下,第二个字符串的C之后的下一个字符低于第一个字符串的下一个字符,所以你应该先从第二个字符串中取出C

通过将字符串保留为字符串,简单的字符串比较将根据需要比较多个字符以确定要使用的字符。

sub lexi {
   my ($str1, $str2) = @_;

   utf8::downgrade($str1);  # Makes sure length() will be fast
   utf8::downgrade($str2);  # since we only have ASCII letters.

   my $final_string = "";
   while (length($str2) && length($str1)) {
      $final_string .= substr($str1 le $str2 ? $str1 : $str2, 0, 1, '');
   }

   $final_string .= $str1;
   $final_string .= $str2;
   print $final_string, "\n";
}

【讨论】:

  • 在排序后检查我选择smaller string lexicographically的更新。
  • 非常感谢@ikegami 我明白了 感谢一百万次。
  • 实际上在条件下我们有限制。 “当它位于堆栈顶部时,他可以从集合中取出一封信。” 所以解决方案不应该使用任何缓存。否则我们的任务设置错误!!!通过使用 $str1 le $str2 您可以比较整个字符串,而不仅仅是最后一个字符,就像在 STACK 中一样
  • @Yevgen Kulik,这是故意的。仅比较 lastnext 字符是错误的。这就是 OP 正在做的事情,这就是他没有得到错误结果的原因。您必须不断比较字符,直到有一个不同为止。我在回答中详细解释了这一点。
【解决方案2】:

代表太少,无法评论因此答案:

如果两个字符匹配,您需要做的是向前看。你目前做了一个简单的文件匹配,在

的情况下
ZABB
ZAAA

你会得到 ZABBZAA,因为第一个匹配 Z 将是 le Z。所以你需要做的(一个很可能不会很有效的天真的解决方案)是只要字符串/字符匹配就继续查找所以:

Z eq Z
ZA eq ZA
ZAB gt ZAA

到那时你会知道第二个字符串是你想要从第一个字符中弹出的字符串。

编辑 您更新了对字符串的排序,但就像我写的那样,您仍然需要向前看。排序将解决上述两个字符串,但会因这两个而失败:

ZABAZA
ZAAAZB
ZAAAZBZABAZA

因为这里的正确答案是 ZAAAZABAZAZB,而您找不到会简单地比较每个字符的字符

【讨论】:

  • since the first match Z will be le Z.你能解释一下吗?
  • 我可以肯定地评论我自己的帖子:在您的代码中,您的前两个字符都是 Z。您正在执行 le(相当于
  • 谢谢@jon 我花了一整天的时间才明白这一点。
猜你喜欢
  • 2018-08-07
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 2015-10-03
  • 2013-07-07
  • 2014-09-10
  • 2012-12-30
相关资源
最近更新 更多