文件压缩

File Compression

我正在尝试通过将字符串转换为字母和数字来压缩它。示例:

INPUT: AAAAbbWWWW

OUTPUT: A4-b2-W4

这是我要运行解决的问题:

当我用 运行 查询 "aaaaaaa" 时,我得到 "a7".

当我用 运行 查询 "aaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbb" 时,我得到 "a12-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2".

我的密码是

List<Character> chars = new ArrayList<Character>();
    for (int i = 0; i < toCompress.length(); i++) {
        chars.add(toCompress.charAt(i));
    }
    List<String> bits = new ArrayList<String>();
    for (int i = 0; i < chars.size(); i++) {
        char toMatch = chars.get(i);
        int matching = 1;
        for (int dontuse = i; dontuse < chars.size(); dontuse++) {
            int x = dontuse + 1;
            if (x >= chars.size()) {
                continue;
            }
            if (chars.get(x) == toMatch && (x - 1 == matching)) {
                matching++;
            }
        }
        if (!bits.contains(toMatch + "" + matching)) {
            bits.add(toMatch + "" + (matching + 1));
            i = i + matching;
        }
    }
    String compressed = "";
    for (int y = 0; y < bits.size(); y++) {
        if (y == (bits.size() - 1)) {
            compressed += bits.get(y);
        } else {
            compressed += bits.get(y) + "-";
        }
    }
    return compressed;

谁能告诉我如何阻止它在除第一个以外的每个片段中只数到二?

针对您的问题的简单算法如下:

private static String compress(String str) {
    StringBuilder compressed = new StringBuilder();
    int i = 0;
    while (i < str.length()) {
        int length = 1;
        while (i < str.length() - 1 && str.charAt(i) == str.charAt(i+1)) {
            length++;
            i++;
        }
        compressed.append(str.charAt(i)).append(length).append('-');
        i++;
    }
    return compressed.deleteCharAt(compressed.length() - 1).toString();
}

它是这样的:当索引 i 处的输入字符串的字符与后面的字符相同时,我们增加一个 length。结果,length 等于后面相同字符的数量。

当我们击中不同的字符时,我们停止循环,存储当前字符及其长度,并为下一个字符再次重复所有这些。

请注意,此算法会将 "compress" 字符串 b 转换为 b1。您没有指定它在此类字符串上的行为方式。如果您不想这样做,您可以在 length 附加到当前压缩字符串之前简单地添加一个检查。

好的,我修好了。这是我所做的:

    List<Character> chars = new ArrayList<Character>();
    List<Character> oChars = new ArrayList<Character>();
    for (int i = 0; i < toCompress.length(); i++) {
        chars.add(toCompress.charAt(i));
    }
    for (char c : chars) {
        if (!oChars.contains(c)) {
            oChars.add(c);
        }
    }
    HashMap<Character, Integer> map = new HashMap<Character, Integer>();
    for (int i = 0; i < chars.size(); i++) {
        try {
            map.put(chars.get(i), map.get(chars.get(i)) + 1);
        } catch (NullPointerException ex) {
            map.put(chars.get(i), 1);
        }
    }
    String compressed = "";
    for (char c : oChars) {
        int amount = map.get(c);
        compressed += c + "" + amount + "-";
    }
    StringBuilder b = new StringBuilder(compressed);
    b.replace(compressed.lastIndexOf("-"), compressed.lastIndexOf("-") + 1, "" );
    compressed = b.toString();
    return compressed;

嗯,你的逻辑不成立。事实上,很难理解你在这里试图做什么。

添加到bits的地方是重要的部分,因为最后你基本上显示了bits中的内容。那么让我们看看那部分。

    if (!bits.contains(toMatch + "" + matching)) {
        bits.add(toMatch + "" + (matching + 1));
        i = i + matching;
    }

因此,重要的是要了解您在哪里更改了 matching

第一个循环针对 a 运行良好验证。但是你的问题是这样的:

        if (chars.get(x) == toMatch && (x - 1 == matching)) {

matching在内循环开始时为1。因此,一旦您进入超出 0 和 1 的 i 范围,x - 1 就不会等于 matching,这意味着 matching 不会更改,它将停留在 1.

所以除了你的第一个字符,你永远不会在 matching 中得到正确的数字,因为它永远不会递增。将 运行 索引与计数进行比较没有意义。