LeetCode - 443 - 压缩字符串(string-compression)

Create by jsliang on 2019-07-29 17:15:442019-07-29 19:37:55

一 目录

不折腾的前端,和咸鱼有什么区别

| 目录 | | --- | | 一 目录 | | 二 前言 | | 三 解题 | |  3.1 解法 - 暴力破解 | |  3.2 解法 - 双指针 |

二 前言

  • 难度:简单

  • 涉及知识:字符串

  • 题目地址:https://leetcode-cn.com/problems/string-compression/

  • 题目内容

给定一组字符,使用原地算法将其压缩。	
压缩后的长度必须始终小于或等于原数组长度。	
数组的每个元素应该是长度为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。

三 解题

小伙伴可以先自己在本地尝试解题,再回来看看 jsliang 的解题思路。

3.1 解法 - 暴力破解

  • 解题代码

var compress = function(chars) {	
  if (chars.length === 1) {	
    return chars.length;	
  }	
  let start = 0;	
  let mark = chars[0];	
  for (let i = 0; i < chars.length; i++) {	
    if (chars[i] !== mark || i === chars.length - 1) {	
      let length = i - start;	
      if (i === chars.length - 1 && chars[i] === chars[i - 1]) {	
        length += 1;	
      }	
      let numberToArr;	
      if (length === 1) {	
        numberToArr = [mark];	
      } else {	
        numberToArr = [mark, ...String(length).split('')];	
      }	
      mark = chars[i];	
      chars.splice(start, length, ...numberToArr);	
      if (length === 1) {	
        i = start + 1;	
      } else {	
        i = start + 2 + (String(length).split('').length - 1);	
      }	
      start = i;	
    }	
  }	
  return chars.length;	
};
  • 执行测试

  1. chars: ["a","a","b","b","c","c","c"]

  2. return

[ 'a', '2', 'b', '2', 'c', '3' ]
  • LeetCode Submit

✔ Accepted	
  ✔ 70/70 cases passed (108 ms)	
  ✔ Your runtime beats 57.64 % of javascript submissions	
  ✔ Your memory usage beats 23.68 % of javascript submissions (37.4 MB)
  • 知识点

  1. split(): split() 方法使用指定的分隔符字符串将一个 String 对象分割成字符串数组,以将字符串分隔为子字符串,以确定每个拆分的位置。 split() 详细介绍

  2. splice(): splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。 splice() 详细介绍

  3. String:将其他值转成字符串。 String 详细介绍

  • 解题思路

首先,解题中的繁杂,不一一道来,一开始我的思路,写出来的题解是这样的:

var compress = function(chars) {	
  if (chars.length === 1) {	
    return chars.length;	
  }	
  let start = 0;	
  let mark = chars[0];	
  for (let i = 0; i < chars.length; i++) {	
    if (chars[i] !== mark || i === chars.length - 1) {	
      let length = i - start;	
      if (i === chars.length - 1 && chars[i] === chars[i - 1]) {	
        length += 1;	
      }	
      let numberToArr;	
      if (length === 1) {	
        numberToArr = [mark];	
      } else {	
        numberToArr = [mark, ...String(length).split('')];	
      }	
      mark = chars[i];	
      chars.splice(start, length, ...numberToArr);	
      if (length === 1) {	
        i = start + 1;	
      } else {	
        i = start + 2 + (String(length).split('').length - 1);	
      }	
      start = i;	
    }	
  }	
  return chars.length;	
};

Submit 是这样的:

✔ Accepted	
  ✔ 70/70 cases passed (108 ms)	
  ✔ Your runtime beats 57.64 % of javascript submissions	
  ✔ Your memory usage beats 23.68 % of javascript submissions (37.4 MB)

然后,咱讲讲思路:

  • ["a"] 这种长度为 1 的情况,直接返回 1 即可。

  • ["a","a","b","b","c","c","c"] 这种正常情况,我们需要统计的是字母变更以及数组结尾的长度。

  • ["a","b","b","b","b","b","b","b","b","b","b","b","b"] 这种长度有 1 的情况,1 不需要体现出来,即不需要 ["a","1"] 这样,并且它的 i 只需要改变 1 位即可。

  • ["a","a","a","b","b","a","a"] 这种长度超过 2 的情况,我们在需要表示成 ["a","3"] 的同时,我们的下表 i 需要加上 2。

  • ["a","a","a","a","a","a","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","c","c","c","c","c","c","c","c","c","c","c","c","c","c"] 这种中间字母长度超过 10 的,我们还需要给下标加上它的长度,例如: ['a','6','b','2','1','c','1','4'],如果不加,那么它会变成 ['a','6','b','2','c','1','4']

  • ……

经过多种尝试最终成功破解本题,代码过于复杂不推荐理解。

最后,我们成功原地修改数组,并返回数组的长度。

3.2 解法 - 双指针

  • 解题代码

var compress = function (chars) {	
  let j = 0,	
    count = 1;	
  chars.push(0);	
  for (let i = 1; i < chars.length; i++) {	
    if (chars[i] !== chars[i - 1]) {	
      chars[j] = chars[i - 1];	
      j++;	
      if (count > 1) {	
        let temp = count.toString();	
        for (let k = 0; k < temp.length; k++) {	
          chars[j++] = temp[k];	
        }	
      }	
      count = 1;	
    } else {	
      count++;	
    }	
  }	
  return j;	
};
  • 执行测试

  1. chars: ["a","a","b","b","c","c","c"]

  2. return

[ 'a', '2', 'b', '2', 'c', '3' ]
  • LeetCode Submit

✔ Accepted	
  ✔ 70/70 cases passed (100 ms)	
  ✔ Your runtime beats 77.78 % of javascript submissions	
  ✔ Your memory usage beats 23.68 % of javascript submissions (37.4 MB)
  • 知识点

  1. push(): push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。 push() 详细介绍

  2. toString(): toString() 返回一个字符串,表示指定的数组及其元素。 toString() 详细介绍

  • 解题思路

看了下大佬的题解,使用的是双指针法。

判断如下:

  1. 给数组增加长度,然后给末尾添加 0。(为什么不直接从 0 开始,请思考对与否)。

  2. 遍历 chars 数组。

  3. 将长度赋值到数组中。

尝试打印下数据:

var compress = function (chars) {	
  let j = 0,	
    count = 1;	
  chars.push(0);	
  for (let i = 1; i < chars.length; i++) {	
    if (chars[i] !== chars[i - 1]) {	
      chars[j] = chars[i - 1];	
      j++;	
      if (count > 1) {	
        let temp = count.toString();	
        for (let k = 0; k < temp.length; k++) {	
          chars[j++] = temp[k];	
        }	
      }	
      count = 1;	
      console.log('------');	
      console.log(chars);	
      console.log(count);	
    } else {	
      count++;	
    }	
  }	
  return j;	
};

Console

------	
[ 'a', '2', 'b', 'b', 'c', 'c', 'c', 0 ]	
1	
------	
[ 'a', '2', 'b', '2', 'c', 'c', 'c', 0 ]	
1	
------	
[ 'a', '2', 'b', '2', 'c', '3', 'c', 0 ]	
1

这样,我们就成功解决了这道题啦~


不折腾的前端,和咸鱼有什么区别!

640?wx_fmt=jpeg

jsliang 会每天更新一道 LeetCode 题解,从而帮助小伙伴们夯实原生 JS 基础,了解与学习算法与数据结构。

扫描上方二维码,关注 jsliang 的公众号,让我们一起折腾!

640?wx_fmt=png

jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值