Java 文件压缩

Java 文件压缩,java,algorithm,compression,Java,Algorithm,Compression,我试图通过将字符串转换成字母和数字来压缩它。例如: 输入:aaaabbww 输出:A4-b2-W4 以下是我遇到的问题: 当我使用查询“aaaaaaaaa”运行它时,我得到“a7” 当我使用查询“aaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbb”运行它时,我得到了“a12-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2-b2” 我的代码是 List<Character> chars

我试图通过将字符串转换成字母和数字来压缩它。例如:

输入:aaaabbww

输出:A4-b2-W4

以下是我遇到的问题:

当我使用查询“aaaaaaaaa”运行它时,我得到“a7”

当我使用查询“aaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbb”运行它时,我得到了“a12-b2-b2-b2-b2-b2-b2-b2-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;
List chars=new ArrayList();
for(int i=0;i=chars.size()){
继续;
}
if(chars.get(x)=toMatch&&(x-1==匹配)){
匹配++;
}
}
如果(!bits.contains(toMatch+“”+匹配)){
添加(toMatch++(匹配+1));
i=i+匹配;
}
}
字符串压缩=”;
对于(int y=0;y

有没有人能告诉我,如何使每一段中只有两个计数,而不是第一个?

解决您问题的简单算法如下:

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();
}
私有静态字符串压缩(字符串str){
StringBuilder compressed=新的StringBuilder();
int i=0;
而(i
它是这样的:虽然索引
i
处的输入字符串的字符与下面的字符相同,但我们增加了
长度
。因此,
长度
等于以下相同字符的数量

当我们击中另一个角色时,我们停止循环,存储当前角色及其长度,然后对下一个角色重复所有这些


请注意,此算法将字符串
b
压缩为
b1
。您没有指定它在此类字符串上的行为方式。如果您不想这样做,只需在添加到当前压缩字符串之前对
长度添加一个检查即可。

好的,我修复了它。以下是我所做的:

    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;
List chars=new ArrayList();
List oChars=new ArrayList();
for(int i=0;i
好吧,你的逻辑并没有真正起作用。事实上,很难理解你想在这里做什么

添加到
的位置是重要的部分,因为最后基本上显示
中的内容。让我们看看这部分

    if (!bits.contains(toMatch + "" + matching)) {
        bits.add(toMatch + "" + (matching + 1));
        i = i + matching;
    }
因此,查看在哪里更改匹配的
非常重要

第一个循环针对
a
运行良好。但您的问题是在这种情况下:

        if (chars.get(x) == toMatch && (x - 1 == matching)) {
匹配
在内部循环的开始处为1。因此,一旦进入超出0和1的
i
范围,
x-1
将不等于
matching
,这意味着
matching
不会改变,它将保持在
1


因此,除了第一个字符外,您永远无法在
匹配中获得正确的数字,因为它永远不会递增。将运行索引与计数进行比较没有意义。

为什么不使用key=char、value=迭代的映射?这将是直截了当的。如果您需要将输出作为字符串,那么将映射转换为所需的字符串也相当容易。我将尝试并发布我的结果。谢谢。@isanco地图中的密钥未订购。我想,这里的输出应该作为输入进行排序。因为他在压缩绳子,这正是我要说的。现在它只是完全随机地抛出它。编辑:我现在在想的是,把每一个字符放在一个列表中,然后根据列表顺序排列它们。考虑引入一个阈值来保持记录比原来的运行时间长。谢谢!这比我的版本要简单得多。好奇的是,大O会是什么样子?N^2或否?@BenKnoble我认为这是O(N),因为字符串只在一次传递中被压缩。