PHP霍夫曼解码算法

时间:2017-09-21 09:29:46

标签: php huffman-code

我最近申请了一份工作,并收到了一个带有几个问题的黑客考试。其中一个是霍夫曼解码算法。有一个类似的问题可用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来获取第一个字符和正则表达式匹配以获得数字,但这仍然通过前两个并且失败了隐藏五。我尝试在黑客等级平台中使用白色空间作为输入,沙盒环境无法处理它,所以我回到上面的解决方案,因为它更优雅。

我尝试使用特殊字符的代码,其他语言的字符,各种大小的代码,并始终返回所需的解决方案。

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

2 个答案:

答案 0 :(得分:1)

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

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

这引出了第二个问题,即您没有检测到此错误。在循环结束后,您应该检查$searchCode是否为空。如果不是,则代码未完成,或代码在中间结束。无论哪种方式,消息相对于提供的前缀代码都是损坏的。问题是否说明了如何处理错误?

我期望使用此代码的唯一真正问题是您没有充分解码代码描述。问题是否总是有两个标签,或者你的结论是什么?也许只是任何数量的空间和标签。还有其他字符编码需要转换为[newline]吗?我认为你确实需要转换它们,如果其中一个例子包含一个。做到了?否则,也许你不应该转换。

答案 1 :(得分:0)

我对编码挑战也有同样的疑问。经过修改的输入是一个列表,其中包含(a 111101,b 110010,[newline] 111111 ....)

我使用了另一种方法来解决此问题,即使用哈希映射,但我仍然只通过了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();

    }

}