杂谈:重复子序列问题

264 阅读1分钟

返回字符串中连续重复单词有多少组,例如:

// str = 'dog DOG cat', 输出:1
// str = 'dog duck dog cat cat', 输出:1
// str = 'cat cat cat dog dog duck ', 输出:2
// str = 'dog      dog cat', 输出:1
// str = '   ', 输出:0
// str = 'dog', 输出:0
  • 题解一:计数法

示例:str = 'a, a, a, b, b, c'

image.png

从图中可以看出,计数器默认1次,然后循环对比,当相同时计数器+1;不同时计数器重置为1,并且计数器大于1则结果值+1。具体代码如下:

function getResult(str) {
    // 边界处理
    if (!str) {
        return 0;
    }
    let arr = str.split(' ').filter( v => v).map(v => v.toLowerCase());
    // 边界处理
    if (arr.length < 2) {
        return 0;
    }
    // 定义结果,并初始化相同的单词数量为1
    let result = 0;
    let buff = 1;
    for (let i = 0; i < arr.length - 1; i++) {
        if (arr[i] === arr[i+1]) {
            // 如果相等,则相同的长度 +1
            buff++
        } else {
            // 如果不相等,有相同的结果 +1,并且将缓存长度重置为 1
            buff > 1 && result++
            buff = 1;
        }
    }
    // 最后结束时如果还有一串相同元素,结果 +1
    buff > 1 && result++
    return result;
}
  • 题解二:操作栈

image.png

从图中可以看出,维护一个栈,当前元素与栈顶元素不相符时,清空栈,将当前元素入栈,并且如果栈长度大于1时,结果值+1

function getResult(str) {
    // 边界处理
    if (!str) {
        return 0;
    }
    let arr = str.split(' ').filter(v => v).map(v => v.toLowerCase());
    // 边界处理
    if (arr.length < 2) {
        return 0;
    }
    // 定义结果
    let result = 0;
    let buffChild = [];

    for (let i = 0; i < arr.length; i++) {
        // 如果子集不相等了,重新进行赋值和更新
        if (buffChild.length && arr[i] !== buffChild[buffChild.length - 1]) {
            buffChild.length > 1 && result++;
            buffChild = [];
            buffChild.push(arr[i]);
            continue;
        }
        // 如果子集为空或者和子集的最后一个元素相同时
        buffChild.push(arr[i]);
    }
    return result;
}

小结

寻找重复单词串的次数,首先找到一个重复的串,可以通过计数或者维护栈的方式,然后在不重复时进行初始值的处理和结果值的计算。