【问题标题】:PHP Huffman Decode AlgorithmPHP 霍夫曼解码算法
【发布时间】:2018-03-02 14:10:36
【问题描述】:

我最近申请了一份工作,并收到了一个hackerrank考试,其中有几个问题。其中一个是霍夫曼解码算法。 here 有一个类似的问题,它比我能更好地解释格式。

实际的任务是接受两个参数并返回解码后的字符串。

第一个参数是代码,它是一个字符串数组,如:

[
    "a      00",
    "b      101",
    "c      0111",
    "[newline]      1001"
]

例如:单个字符、两个制表符、霍夫曼代码。

由于黑客等级的设置方式,换行符被指定为这种格式。

第二个参数是使用代码解码的字符串。例如:

101000111 = bac

这是我的解决方案:

function decode($codes, $encoded) {
    $returnString = '';
    $codeArray = array();

    foreach($codes as $code) {
        sscanf($code, "%s\t\t%s", $letter, $code);
        if ($letter == "[newline]")
            $letter = "\n";
        $codeArray[$code] = $letter;
    }
    print_r($codeArray);

    $numbers = str_split($encoded);
    $searchCode = '';
    foreach ($numbers as $number) {
        $searchCode .= $number;
        if (isset($codeArray[$searchCode])) {
            $returnString .= $codeArray[$searchCode];
            $searchCode = '';
        }
    }

    return $returnString;
}

它通过了两个初始测试,但还有另外五个隐藏测试没有通过并且没有给出任何反馈。

我意识到如果字符是空格,这个解决方案不会通过,所以我尝试了一个不太理想的解决方案,使用 substr 来获取第一个字符并使用正则表达式匹配来获取数字,但这仍然通过了前两个并且失败了隐藏五。我在黑客等级平台中尝试了使用空白作为输入的功能,但沙盒环境无论如何都无法处理它,所以我恢复到上述解决方案,因为它更优雅。

我尝试了带有特殊字符、其他语言字符、各种大小的代码的代码,它总是返回所需的解决方案。

我很沮丧,因为我发现这是一个优雅的解决方案,所以我找不到导致此失败的案例。鉴于没有空白,我希望得到一些关于为什么这可能会失败的反馈,以及关于性能提升的任何反馈。

【问题讨论】:

  • 他们是否对允许使用的内置功能有任何限制?如果没有,我会用代码构建一个数组,用替换构建一个数组——然后简单地使用 str_replace,这将一次性完成所有工作。唯一的要求是您首先按长度按降序对代码进行排序。
  • 允许使用任何内置的 PHP 函数,这是一个有趣的解决方案,但我认为这不会很好,因为可能会出现意外匹配,其中数字与意外位置的字母匹配.代码可以是可变长度的,因此您也不能先将它们分开。
  • 代码对我来说看起来不错。但是:(1)是否还有其他类似[newline] 这样的代码,您需要处理这些代码? (2) 您是否必须遵守时间限制(对于非常大的输入)? (3) 当发现编码的字符串是无效序列时,函数是否必须给出特定的输出?
  • (4) 输入字符串可以有多字节字符吗?如果是这样,您需要使用 str_split 以外的其他内容,因为这会将字符串拆分为字节,而不是字符。
  • 谢谢,我确信这是非常好的代码,它让我质疑环境,因为它不支持空格。我只是不想听起来疯狂地指责环境。 1) 换行被明确提到是唯一的情况。 2)有超时限制,但当时没有达到,这是一个特定的失败案例。 3)没有提到如果它无效会发生什么 4)这是一种可能性,但哈夫曼压缩的想法是它是二进制的,所以在代码字符串中应该只是 0 或 1

标签: php huffman-code


【解决方案1】:

您的基本方法是合理的。由于霍夫曼代码是前缀代码,即没有代码是另一个代码的前缀,那么如果您的搜索找到匹配项,那么它一定是代码。您的代码的后半部分适用于任何适当的 Huffman 代码以及使用它编码的任何消息。

一些cmets。首先,您提供的示例不是霍夫曼代码,因为前缀 0100110100011 不存在。霍夫曼码是完整的,而这个前缀码不是。

这带来了第二个问题,即您没有检测到此错误。您应该在循环结束后检查$searchCode 是否为空。如果不是,那么代码不完整,或者代码在中间结束。无论哪种方式,消息就提供的前缀代码而言是损坏的。问题是否指定了如何处理错误?

我认为这段代码唯一真正的问题是你没有对代码描述进行足够的解码。问题是说总是有两个标签,还是你得出结论?也许它只是任意数量的空间和标签。您需要在哪里转换像[newline] 这样的其他字符编码?如果有效的示例之一包含一个,我认为您实际上确实需要转换它们。做到了?否则,也许你不应该转换。

【讨论】:

    【解决方案2】:

    我对编码挑战有同样的问题。进行了一些修改,因为输入是一个带有 (a 111101,b 110010,[newline] 111111 ....) 的列表

    我采用了不同的方法来解决它,使用 hashmap,但我也只通过了 2 个示例测试用例。

    下面是我的代码:

    public static String decode(List<String> codes, String encoded) {
        // Write your code here
             String result = "";
             String buildvalue ="";
             HashMap <String,String> codeMap= new HashMap<String,String>();
            for(int i=0;i<codes.size();i++){
               String S= codes.get(i);
               String[] splitedData = S.split("\\s+"); 
               String value=splitedData[0];
               String key=(splitedData[1].trim());            
             codeMap.put(key, value);
            }
            for(int j=0;j<encoded.length();j++){
                  buildvalue+=Character.toString(encoded.charAt(j));
                  if(codeMap.containsKey(buildvalue)){
                      if(codeMap.get(buildvalue).contains("[newline]")){
                        result+="\n";
                        buildvalue="";
                      }
                      else{
                       result+=codeMap.get(buildvalue);
                       buildvalue="";
                      }
                  }
             }
             return result.toString();
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多