如何压缩字符串

时间:2015-12-08 09:34:35

标签: string algorithm compression

我的一次采访中有这个问题:

  

给定一个字符串你会如何压缩它?

示例输入的格式不是aabbccdd,而是abcdgehrk。即chars中的所有string都不同。(注意:运行长度编码不起作用,因为它是我给出的解决方案之一,但他说字符串没有任何重复字符)

我给出了以下两种解决方案,但他不接受这些解决方案:

1)HashCode不能成为解决方案,因为它会存储数字
2)不能以二进制形式存储,因为它不是人类可读的格式

任何人都可以建议这个问题可能是另一种解决方案吗?

3 个答案:

答案 0 :(得分:4)

鉴于审查员要求压缩字符串是人类可读的,一个解决方案是Run-Length Encoding

因此,aabbccdd将被压缩为2a2b2c2d,而abcdgehrk将被压缩为1a1b1c1d1g1e1h1r1k。

请注意,这些特殊示例中的输出字符串不短于原始字符串,但它是所有无损压缩算法的属性,它们无法保证对任何输入数据集进行压缩。

答案 1 :(得分:1)

如果要求允许字符串仅由小写字母字符组成,则每个字符可以适合5位(2 ^ 5 = 32个可能的字符)。然后,一个8个字符的字符串可以适合40位= 5个字节。

这是一个例子,将3个字符装入2个字节:

a = 00001
b = 00010
c = 00011

字符串" cab"适合:

  c     a     b   (extra bit)
00011 00001 00010 0

00011000 01000100

以big-endian形式:

0x1844

人类可读的要求很愚蠢。对于任何这种性质的东西,都需要软件和标准(例如ASCII)才能被人阅读。使用合适的软件和输出设备,任何东西都是人类可读的。

答案 2 :(得分:0)

我之前已经解决了这个问题,我将包含字符串,例如(aaabb),此过程将变为(a3b1),然后我将检查包含字符串的长度是否小于原始字符串的长度,我将返回包含字符串否则返回原始 (ab)->(a1b1)在这种情况下,我将返回原始字符串。 (aaaaabb)->(a5b2)在这种情况下,我将返回包含字符串。 这是我的代码,需要O(N)

   public static String stringCompression(String str){

    StringBuilder compressed  = new StringBuilder();
    int count = 1;
    int i = 0;
    for ( i = 0; i <str.length()-1 ; i++) {
        if(str.charAt(i) == str.charAt(i+1)){
       //     System.out.println("str.charAt(i) = " + str.charAt(i));
            count++;
        }
        else {
            compressed.append(str.charAt(i)).append(count);
            count =1;
        }
    }

    if(i == str.length()-1)
        compressed.append(str.charAt(i)).append(count);

    return compressed.length() < str.length() ? new String(compressed): str;
}

您可能会使用此算法反解析数据

public static String stringDeCompression(String str){
   StringBuilder stringBuilder = new StringBuilder();
   int temp = 0;
   int k = 0;
   for (int i = 1; i <str.length() ; i+=2) {
        temp = Character.getNumericValue(str.charAt(i));
       for (int j = 0 ; j < temp ; j++) {
           stringBuilder.append(str.charAt(k));
       }
       k+=2;
    }
   return new String(stringBuilder);
}