Java compressing Strings

2019-01-06 19:58发布

I need to create a method that receives a String and also returns a String.

Ex input: AAABBBBCC

Ex output: 3A4B2C

Well, this is quite embarrassing and I couldn't manage to do it on the interview that I had today ( I was applying for a Junior position ), now, trying at home I made something that works statically, I mean, not using a loop which is kind of useless but I don't know if I'm not getting enough hours of sleep or something but I can't figure it out how my for loop should look like. This is the code:

public static String Comprimir(String texto){

    StringBuilder objString = new StringBuilder();

    int count;
    char match;

        count = texto.substring(texto.indexOf(texto.charAt(1)), texto.lastIndexOf(texto.charAt(1))).length()+1;
        match = texto.charAt(1);
        objString.append(count);
        objString.append(match);

    return objString.toString();
}

Thanks for your help, I'm trying to improve my logic skills.

17条回答
Summer. ? 凉城
2楼-- · 2019-01-06 20:43

The following can be used if you are looking for a basic solution. Iterate through the string with one element and after finding all the element occurrences, remove that character. So that it will not interfere in the next search.

public static void main(String[] args) {
    String string = "aaabbbbbaccc";
    int counter;
    String result="";
    int i=0;
    while (i<string.length()){
        counter=1;
        for (int j=i+1;j<string.length();j++){ 
            System.out.println("string length ="+string.length());  
            if (string.charAt(i) == string.charAt(j)){
                  counter++;
            }
      }
      result = result+string.charAt(i)+counter; 
      string = string.replaceAll(String.valueOf(string.charAt(i)), ""); 
    }
    System.out.println("result is = "+result);
}

And the output will be := result is = a4b5c3

查看更多
叼着烟拽天下
3楼-- · 2019-01-06 20:44
  • use StringBuilder (you did that)
  • define two variables - previousChar and counter
  • loop from 0 to str.length() - 1
  • each time get str.charat(i) and compare it to what's stored in the previousChar variable
  • if the previous char is the same, increment a counter
  • if the previous char is not the same, and counter is 1, increment counter
  • if the previous char is not the same, and counter is >1, append counter + currentChar, reset counter
  • after the comparison, assign the current char previousChar
  • cover corner cases like "first char"

Something like that.

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-01-06 20:44

In the count=... line, lastIndexOf will not care about consecutive values, and will just give the last occurence.

For instance, in the string "ABBA", the substring would be the whole string.

Also, taking the length of the substring is equivalent to subtracting the two indexes.

I really think that you need a loop. Here is an example :

public static String compress(String text) {
    String result = "";

    int index = 0;

    while (index < text.length()) {
        char c = text.charAt(index);
        int count = count(text, index);
        if (count == 1)
            result += "" + c;
        else
            result += "" + count + c;
        index += count;
    }

    return result;
}

public static int count(String text, int index) {
    char c = text.charAt(index);
    int i = 1;
    while (index + i < text.length() && text.charAt(index + i) == c)
        i++;
    return i;
}

public static void main(String[] args) {
    String test = "AAABBCCC";
    System.out.println(compress(test));
}
查看更多
Juvenile、少年°
5楼-- · 2019-01-06 20:47

It may help you.

public class StringCompresser
{
public static void main(String[] args)
{
    System.out.println(compress("AAABBBBCC"));
    System.out.println(compress("AAABC"));
    System.out.println(compress("A"));
    System.out.println(compress("ABBDCC"));
    System.out.println(compress("AZXYC"));
}

static String compress(String str)
{
    StringBuilder stringBuilder = new StringBuilder();
    char[] charArray = str.toCharArray();
    int count = 1;
    char lastChar = 0;
    char nextChar = 0;
    lastChar = charArray[0];
    for (int i = 1; i < charArray.length; i++)
    {
        nextChar = charArray[i];
        if (lastChar == nextChar)
        {
            count++;
        }
        else
        {
            stringBuilder.append(count).append(lastChar);
            count = 1;
            lastChar = nextChar;

        }
    }
    stringBuilder.append(count).append(lastChar);
    String compressed = stringBuilder.toString();

    return compressed;
} 
}

Output:

3A4B2C
3A1B1C
1A
1A2B1D2C
1A1Z1X1Y1C
查看更多
可以哭但决不认输i
6楼-- · 2019-01-06 20:47

The answers which used Map will not work for cases like aabbbccddabc as in that case the output should be a2b3c2d2a1b1c1.

In that case this implementation can be used :

private String compressString(String input) {
        String output = "";
        char[] arr = input.toCharArray();
        Map<Character, Integer> myMap = new LinkedHashMap<>();
        for (int i = 0; i < arr.length; i++) {
            if (i > 0 && arr[i] != arr[i - 1]) {
                output = output + arr[i - 1] + myMap.get(arr[i - 1]);
                myMap.put(arr[i - 1], 0);
            }
            if (myMap.containsKey(arr[i])) {
                myMap.put(arr[i], myMap.get(arr[i]) + 1);
            } else {
                myMap.put(arr[i], 1);
            }
        }

        for (Character c : myMap.keySet()) {
            if (myMap.get(c) != 0) {
                output = output + c + myMap.get(c);
            }
        }

        return output;
    }
查看更多
登录 后发表回答