题目描述:
给定一组字符,使用原地算法将其压缩。
压缩后的长度必须始终小于或等于原数组长度。
数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。
在完成原地修改输入数组后,返回数组的新长度。
进阶:
你能否仅使用O(1) 空间解决问题?
示例 1:
输入:
["a","a","b","b","c","c","c"]
输出:
返回6,输入数组的前6个字符应该是:["a","2","b","2","c","3"]
说明:
"aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
示例 2:
输入:
["a"]
输出:
返回1,输入数组的前1个字符应该是:["a"]
说明:
没有任何字符串被替代。
示例 3:
输入:
["a","b","b","b","b","b","b","b","b","b","b","b","b"]
输出:
返回4,输入数组的前4个字符应该是:["a","b","1","2"]。
说明:
由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
注意每个数字在数组中都有它自己的位置。
注意:
- 所有字符都有一个ASCII值在
[35, 126]
区间内。 1 <= len(chars) <= 1000
。
代码:
class Solution {
public int compress(char[] chars) {
if(chars.length==0)
return 0;
int m=0,i=0,j;
while(i<chars.length){
j=i; //i指向每一个字母第一次出现的下标
chars[m++]=chars[i]; //m从0开始,每次换一个字符则自增1
int k=0;
while(j<chars.length&&chars[i]==chars[j]){//判断是否是同一个字母
k++; //k统计的是每个字母的个数
j++;
}
StringBuilder sb=new StringBuilder();
if(k!=1){ //如果字母只出现一次不用加数字
while(k!=0){
sb.append((char)(k%10+48)); //假设一个字符出现的个数是23,则转化为‘3’,‘2’两个字符
k/=10;
}
}
sb.reverse(); //'3''2'反转为‘2’‘3’;
for(char c:sb.toString().toCharArray()){System.out.println("c="+c);
chars[m++]=c; //把‘2’‘3’插入chars[]
}
i=j;
}
return m;
}
}