需求:
给定一个字符数组chars,由若干个字符组成,现对其进行简化,比如”aaabbcc”,将其转化成”a3b2c2″
,如果字符个数是1,那么不需要进行简化。要求in-place,即直接修改原始字符数组。
分析:
1)特殊情况处理:如果字符数组是null,那么抛出参数异常;如果字符数组长度是0或者1,那么无需进行简化,直接返回数组长度即可。
2)定义三个变量,字符变量ch,存储出现的字符,整型变量num,存储每个字符的出现次数,整型变量index,维护更新后字符数组的长度。ch初始化为第一个字符,num初始化为1,index初始化为0。从第二个字符开始遍历字符数组,如果当前字符和ch相同,那么num++,如果不同,说明已经求完上一个片段的字符个数,更新字符数组,chars[index++] = ch
,判断num是否为1,如果不为1,那么需要将num转成字符串,依次添加到chars数组中,然后更新ch为当前字符,num更新为1,循环此过程。
3)对于最后一个字符段,和过程2)相似,更新chars[index++] = ch
,如果出现次数num不是1,那么需要将其转成字符串,添加到chars中,如果次数num是1,那么不需要更新chars数组。
4)新的数组长度一定小于等于原始的数组长度。因为如果原始字符数组中字符出现次数是1,那么不需要简化修改,如果是2,比如”aa”,那么简化之后是”a2″,更新之后的数组和原始数组长度相同,如果次数大于2,那么更新之后的长度一定是小于原始长度的,所以index一定小于等于遍历的角标,不会出现覆蓋还未被遍历的字符的情况。
时间复杂度:O(N)。
空间复杂度:O(1)
代码:
class Solution {
public int compress(char[] chars) {
//异常处理
if(chars == null)
throw new IllegalArgumentException("illegal parameters");
//如果chars长度是0或者1,那么不需要进行简化,直接返回其长度
if(chars.length == 0 || chars.length == 1)
return chars.length;
//定义三个变量
//char ch: 存储当前字符段对应的字符
//int num: 存储当前字符段字符ch出现的次数
//int index: 维护有效的数组长度
char ch = chars[0];
int num = 1;
int index = 0;
for(int i = 1; i < chars.length; i++){
if(chars[i] == ch)
num++;
else{
//说明先前的字符段已经遍历完,需要更新字符数组
chars[index++] = ch;
if(num > 1){
String s = num+"";
for(int j = 0; j < s.length(); j++)
chars[index++] = s.charAt(j);
}
//更新ch和num
ch = chars[i];
num = 1;
}
}
//对最后一个字符段进行单独处理
chars[index++] = ch;
if(num > 1){
String s = num+"";
for(int i = 0; i < s.length(); i++)
chars[index++] = s.charAt(i);
}
return index;
}
}