手摸手提桶跑路——LeetCode443. 压缩字符串

117 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

题目描述

给你一个字符数组 chars,请使用下述算法压缩:

从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符:

  • 如果这一组长度为 1 ,则将字符追加到 s 中。
  • 否则,需要向 s 追加字符,后跟这一组的长度。

压缩后得到的字符串 s 不应该直接返回 ,需要转储到字符数组 chars 中。需要注意的是,如果组长度为 1010 以上,则在 chars 数组中会被拆分为多个字符。

请在 修改完输入数组后 ,返回该数组的新长度。

你必须设计并实现一个只使用常量额外空间的算法来解决此问题。

解题思路——计数

题目很清楚,就是统计 连续 的相同字符的数量,数量为 1 的直接将字符返回,大于 1 的需要返回字符以及其数量。例如 ['a','b','b'] 需要变为 ['a','b','2']

需要注意的是这里的数量是要按高到低去排列到数组中的,比如 12 个连续字符 a,那么结果就是 ['a','1','2'] 了。还有一个注意点是这道题要求 常量额外空间,也就是说我们需要在原数组上做文章,才能保证常量的空间复杂度。

具体步骤如下:

  1. 初始化一个 end 指针,用于标记已经处理好的下标,计数变量 cnt=0,变量 curWord 用来记录当前计数的字符。
  2. 遍历 chars 数组,一开始 curWord 为空,直接处理,让 curWord 指向,同时 cnt = 1;如果遍历到当前字符仍然是 curWord,则 cnt++,否则修改原 chars 数组,将 curWord 放入 chars 数组的 end 下标处,同时判断 cnt 是否为 1,不为 1 则需要将 cnt 继续往 end 的后一个地方放置。
  3. 重复步骤 2,得到最终 end 的值,就是压缩后的最后一个字符的下标,输出。

题解

/**
 * @param {character[]} chars
 * @return {number}
 */
var compress = function(chars) {
    let cnt = 0, curWord = '', end = 0;
   
    for(let w of chars) {
        if(curWord === '') {
            cnt++;
            curWord = w;
        } else if(curWord === w) {
            cnt++;
        } else {
            chars[end++] = curWord;
            if(cnt != 1) {
                for(let w of `${cnt}`) {
                    chars[end++] = w;
                }
            }
            curWord = w;
            cnt = 1;
        }
    }
    chars[end++] = curWord;
    if(cnt != 1) {
        for(let w of `${cnt}`) {
            chars[end++] = w;
        }
    }
    return end;
};

捕获.PNG