[前端]_一起刷leetcode 763. 划分字母区间

186 阅读3分钟

这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

题目

763. 划分字母区间

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

 

示例:

输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

 

提示:

  • S的长度在[1, 500]之间。
  • S只包含小写字母 'a' 到 'z' 。

思路

  1. 我们要根据片段来切割,然后相同字符的在同一个片段中,那么我们可以转换一下这个问题,先通过一轮遍历统计出每个元素最后一次出现在字符串中的位置;
  2. 由于题目中已经说了元素全部是小写字母,所以我们可以新建一个26位长度的数组来记录每个元素最后一次出现的位置,一开始默认值都是-1表示没有出现过;当然如果这道题目没有说全部是小写字母怎么办呢,我们可以用map来记录,都差不多,只不过map每一轮需要getset没有直接修改索引值来得直观;
  3. 那么数组的下标怎么跟元素的abcd进行关联呢,这道题目中我们可以通过charCodeAt方法来实现,这个方法是把小写字母转成数字的,不过转成数字后是从第97位开始的,前面的拿来存放其他字符了,而且是有序的并且与字母一一对应,所以我们只需要拿到每个位置的字符通过charCodeAt转换后就可以存入数组的下标中去,然后一轮for循环跑完,后面出现的值自然会覆盖前面的值,就实现了对最后出现的位置的统计;
  4. 然后再跑一次for循环,用三个变量来记录,prev记录上一个元素出现的位置,maxLen记录当前元素的最大长度,当我们走到一个位置的时候,判断一下是否已经是前面元素出现过的最大长度位置,如果是的话说明可以切割;
  5. 那么我们只需要把当前索引i减去上一轮出现的位置prev,就可以计算出长度了,把长度放到result数组中去即可。

实现

/**
 * @param {string} s
 * @return {number[]}
 */
var partitionLabels = function(s) {
    const lastCharArr = new Array(26).fill(-1);

    // 统计每个元素最后一次出现的位置
    for (let i = 0; i < s.length; i++) {
        const num = s[i].charCodeAt() - 97;
        lastCharArr[num] = i;
    }

    // 索引0的位置也要算长度,所以初始值设置个-1
    let prev = -1;
    let maxLen = 0;
    let result = [];

    for (let i = 0; i < s.length; i++) {
        const num = s[i].charCodeAt() - 97;
        // 当前最长能走的距离 = 上一轮最长距离 或者 当前元素最长距离
        maxLen = Math.max(maxLen, lastCharArr[num]);

        // 当最长距离只能走到这了,说明可以切割了
        if (maxLen <= i) {
            result.push(maxLen - prev);
            prev = maxLen;
            maxLen = 0;
        }
    }

    return result;
};

结果

image.png

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。