5.<tag-字符串和双指针>-lt.443. 压缩字符串
lt.443. 压缩字符串
[案例需求]

[思路分析]
- 题目要求是遍历整个字符数组, 把每个字符都以去重的方式记录下来, 并在字符后面添加上字符在数组中出现的次数;
- 注意:
- 只出现一次的不记录次数
- 重复十几次, 几百次的那种, 要把重复次数单独分割成数字进行存储, 本题稍微复杂一点的地方就在这里了;
- 我们可以把重复次数进行不断的 % 10 和 /10操作,
- 模运算(%)主要是为了取一个数的最末位的数字. 比如 25我要取到5的话就要用 25 % 10;
- 除运算(/)主要是为了让数字降低维度, 比如 256我要取到5这个数字, 就需要 256 / 10 = 25, 然后再用 25 % 10 = 5, 才能取到5;
- 上面的取数过程是反的(比如 256, 我上面一番操作, 变为了 ‘6’, ‘5’, ‘2’), 所以我们还需要把这个数字进行反转 (‘2’, ‘5’, ‘6’)才行;
讲完了细节, 大致说一下整个程序的实现思路:
- 遍历字符数组. 不断的比较当前字符chars[i] 是否还跟 chars[i+ 1] 相等, 同时记录下重复次数 count;
- 当字符不相等之后, 要把前面遍历的字符
char[i]存入数组, 接着还要存入他的重复次数 count; - 为了节省时空,. 我们可以直接在原来的字符数组上进行操作.
[代码实现]
class Solution {
public int compress(char[] chars) {
List<Character> list = new ArrayList<>();
//遍历字符数, 当这个字符跟前一个相等时, 数量 + 1, 字符串后移;
// 当这个字符与前一个不相等, 把这个字符添加到原来的字符数组中, 然后把数量也添加进去, 然后把数量置为0. 后移指针;
int count = 1;
// int i = 1;
int len = chars.length;
int index = 0;
int anchor = 0;
for(int i = 0; i < len; ){
while(i < len - 1 && chars[i] == chars[i + 1]){
++count;
++i;
}
chars[index++] = chars[i];
if(count > 1){ //字符的数量 > 1时才会把字符数量count放入到字符数组
anchor = index; // anchor是为了记住数字的起始位置
while(count > 0){
chars[index++] = (char)(count % 10 + '0'); //字符数量 非常大时, 需要取出个十百位单独储存
count /= 10; //向前进位, 上面存储的是个位, 把我下一步就要存储十位, 百位
}
reverse(chars, anchor, index - 1); //因为上面是按照个十百位顺序存入数组的, 需要反转才对
}
count = 1;
++i;
}
return index;
}
public void reverse(char[] chars, int left, int right){
while(left < right){
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
++left;
--right;
}
}
}
改进:
- 题目要求O(1)空间复杂度,如果用 String.valueOf()的话会创建一个长度为数字位数的字符串和byte数组,理论上就不是常数空间复杂度啦


浙公网安备 33010602011771号