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),因为字符串只在一次传递中被压缩。