2015-09-13 10 views
0

Я пытаюсь сжать строку, превратив ее в буквы и цифры. Пример:Сжатие файлов

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; 

Может кто-нибудь сказать мне, как остановить его только считать до двух в каждом сегменте, но в первую очередь?

+0

Почему вы не используете карту с ключом = char и значением = #iteration? Это было бы просто. Если вам нужен ваш вывод в виде строки, также довольно легко преобразовать карту в нужную строку. – isanco

+0

Я вижу. Я попробую это и опубликую свои результаты. Благодарю. –

+0

@isanco На карте ключи не заказываются. Думаю, здесь вывод должен быть заказан как вход. потому что он сжимает строку. – YoungHobbit

ответ

1

Простой алгоритм для задачи будет следующим:

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 тогда равно числу следующих символов, которые являются одинаковыми.

Когда мы нажимаем другой символ, мы останавливаем цикл, сохраняем текущий символ и его длину и повторяем все это снова для следующего символа.

Обратите внимание, что этот алгоритм «сжимает» строку b в b1. Вы не указали, как он должен себя вести на таких строках. Если вы этого не хотите, вы можете просто добавить чек на length, прежде чем он будет добавлен к текущей сжатой строке.

+0

Спасибо! Это намного проще, чем моя версия. –

+0

Любопытно, как бы выглядел большой О? N^2 или нет? –

+0

@BenKnoble Я думаю, что это O (N), поскольку String сжимается только в один проход. – Tunaki

0

Хорошо, я исправил его. Вот что я сделал:

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; 
+0

Теперь реализация этого на самом деле не работает. –

0

Ну, ваша логика на самом деле не работает. На самом деле, довольно сложно понять, что вы пытаетесь сделать здесь.

Место, где вы добавляете 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 в начале внутреннего цикла. Поэтому, как только вы попадаете в диапазоны i, которые находятся за пределами 0 и 1, x - 1 не будет равняться matching, а это значит, что matching не изменится, он останется на уровне 1.

Таким образом, кроме вашего первого символа, вы никогда не получите правильный номер в matching, потому что он никогда не будет увеличиваться. Нет смысла сравнивать текущий индекс с подсчетом.

Смежные вопросы