zoukankan      html  css  js  c++  java
  • LeetCode --- 字符串系列 --- 分割平衡字符串

    分割平衡字符串

    题目

    在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的。

    给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。

    返回可以通过分割得到的平衡字符串的最大数量。


    示例

    示例 1:
    
    输入:s = "RLRRLLRLRL"
    输出:4
    解释:s 可以分割为 "RL", "RRLL", "RL", "RL", 每个子字符串中都包含相同数量的 'L' 和 'R'。
    
    示例 2:
    
    输入:s = "RLLLLRRRLR"
    输出:3
    解释:s 可以分割为 "RL", "LLLRRR", "LR", 每个子字符串中都包含相同数量的 'L' 和 'R'。
    
    示例 3:
    
    输入:s = "LLLLRRRR"
    输出:1
    解释:s 只能保持原样 "LLLLRRRR".
    
    示例 4:
    
    输入:s = "RLRRRLLRLL"
    输出:2
    解释:s 可以分割为 "RL", "RRRLLRLL", 每个子字符串中都包含相同数量的 'L' 和 'R'。
    

    来源:力扣(LeetCode)

    链接:https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/

    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


    解题思路

    单看上面前三个例子,很容易让人理解错题意

    所以我加上了第四个例子

    主要在于对字符串的动作是 分割,而不是 切割

    处理字符串过程不能舍弃字符串

    分割 不舍弃字符串, 切割 会舍弃字符串

    本题的题意是 分割 。所以难度是简单

    平民思路:
    1、
        定义两个对象 A,B。用来存储 R 和 L 当前的字符计数
        A = { R: 0, L: 0 }
        B = { R: 0, L: 0 }
    2、
        循环 `平衡字符串` ,判断第一个字符是 R 或者 L,则 A 里面的 R 或 L 属性计数加 1
    3、
        计算 A 对象中 R 和 L 的 `计数总和 alen`,用该 `计数总和 alen` 截取 `平衡字符串` ,得到用来做对比的字符串 BChar
        例如 A 中,占据 `平衡字符串` 前两位,则需要第三和第四位与前两位做对比
        即 BChar = string.slice(alen, alen * 2)
    4、
        循环 Bchar,判断第一个字符是 R 或者 L,则 B 里面的 R 或 L 属性计数加 1
    5、
        此时判断是否满足 `平衡字符串` 条件
        A 里面的 R 计数等于 B 里面的 L 计数: A['R'] === B['L']
        并且 
        A 里面的 L 计数等于 B 里面的 R 计数: A['L'] === B['R']
    6、
    6、1
        若满足平衡条件,则
        count 加 1
        且 A 重置为 A = { R: 0, L: 0 }
        字符串截取掉对比过的字符串 A + B
        重置 B 为 B = { R: 0, L: 0 }
        循环变量 index 设置为 -1,方便下次循环 index++ 时设置为 0
        继续循环
    6、2
        若不满足,则重置 B 为 B = { R: 0, L: 0 }
        继续循环
    
    

    或者

    力扣他人题解

    1、
        思考 `平衡字符串` 特性,需要一个 `分割子串` 中的 R 和 L 是相等的
        使用 `出栈入栈` 的方式可以简单明了的解决这个问题
    2、
        遍历 `平衡字符串` ,判断第一个字符串是否是 L
        若是,则入栈, stack++,加 1
        若不是,则出栈,stack--,减 1
    3、
        这样,如果遍历的前两个字符不一样, stack 加 1,而后又减 1,此时 stack 等于 0
        满足 `平衡字符串` 的条件,那么 count++ 加 1 
    

    题解

    此方法是解题常规思路,算是平民解法

    所以性能并不是很好,还有点啰嗦

    下面给出了力扣题解中比较好的一种解法

     let balancedStringSplit = function(s) {
        let count = 0
        let string = s
        let A = {}, B = {}
        for (let i = 0; i < string.length; i++) {
            // 判断字符是 R 或者 L,则 A 里面的 R 或 L 属性计数加 1
            if (!A[string[i]]) {
                A[string[i]] = 1
            } else {
                A[string[i]]++
            }
            // 计算 A 对象中 R 和 L 的计数总和 alen
            let alen = 0
            Object.keys(A).forEach(key => {
                alen += A[key]
            })
            // 用该总和长度 alen 截取 平衡字符串,得到 用来做对比的字符串 BChar
            // 例如 A 中,占据 平衡字符串前两位,则需要第三和第四位与前两位做对比
            let BChar = string.slice(alen, alen * 2)
    
            // 循环 Bchar,判断字符是 R 或者 L,则 B 里面的 R 或 L 属性计数加 1
            for (let c of BChar) {
                if (!B[c]) {
                    B[c] = 1
                } else {
                    B[c]++
                }
            }
    
            // 判断是否满足平衡字符串条件
            if (A['R'] === B['L'] && A['L'] === B['R']) {
                count++
                i = -1 // 让 i 从 0 开始,这里为 -1,经过循环 + 1 就变成 0 了
                A = {}
                // 字符串截取掉对比过的字符串 A + B
                string = string.slice(alen * 2)
            }
            B = {} // 每次都要重置
        }
        return count
    };
    

    或者

    力扣他人题解

    let balancedStringSplit = function(s) {
        let count = 0
        let stack = 0
        for (let i = 0, len = s.length; i < len; i++ ){
            // 遍历 `平衡字符串` ,判断第一个字符串是否是 L
            // 若是,则入栈, stack++,加 1
            // 若不是,则出栈,stack--,减 1
            if(s[i] === 'L') {
                stack++
            } else {
                stack--
            }
            // stack 等于 0, 满足 `平衡字符串` 的条件,那么 count++ 加 1 
            if (stack === 0) {
                count++ 
            }
        }
        return count
    };
    

    备注

    如果没有第四个示例,可能造成误解题意。理解为切割字符串,找出平衡子串

    并且该平衡子串还是必须是 对称互斥子串。 例如 LLLRRR RL LRLR LLRLRLRR

    一开始我理解的就是这样,难得当初写了 N 久,这里也一并贴上算法吧。

    但是用的是暴力遍历计算,本来应该要用马拉车算法吧。但是我还没学。先这样吧


    思路

    1、
    创建数组 A
    循环 字符串 string
    string[i] push 进 A 中
    
    渐进思路 1
    1、
        判断 A 的长度如果等于 2
    1、1
        继续判断 A 的两个元素是否不一样
            如果不一样,则将这两个元素从 chars 切割出去, T 存储这两个元素
            如果一样,继续循环
    2、 
        判断 A 的长度如果大于 2
    2、1
        继续判断 A 的长度是否是 2 的倍数
            如果是,对 A 进行对半切割
                然后 [0].join('')  和 [1].reverse().join('') 遍历对比是否全不相等
                如果全不相等,则将这些元素从 chars 切割出去, count++, 外层循环的 index 重置为 内层循环的位置数值,等待下一个外循环 + 1,继续循环
            如果不是,继续循环
    最后,返回 T
    
    
    渐进思路 2
    1、
        判断 A 的长度是否是 2 的倍数
    1、1
        如果是,对 A 进行对半切割
            然后 [0].join('')  和 [1].reverse().join('') 遍历对比是否全不相等
            若全不相等,则将这些元素从 chars 切割出去, count++, 外层循环的 index 重置为 内层循环的位置数值,等待下一个外循环 + 1,继续循环
        如果不是,继续循环
    最后,返回 T
    
    

    解法

    let balancedStringSplit = function(s) {
        let A = [], count = 0
        let string = s
        for (let i = 0; i < string.length; i++) {
            A = []
            A.push(string[i])
            for (let k = i + 1; k < string.length; k++) {
                A.push(string[k])
                let alen = A.length
                // 判断 A 的长度是否是 2 的倍数
                if (A.length % 2 === 0) {
                    let judge = true
                    let arr = A.slice(0, alen / 2)
                    let brr = A.slice(alen / 2).reverse()
                    // [0].join('') 和 [1].reverse().join('') 遍历对比是否全不相等
                    for (let n = 0; n < arr.length; n++) {
                        if (arr[n] === brr[n]) {
                            judge = false 
                            break;
                        }
                    }
                    // 若全不相等,则将这些元素从 chars 切割出去, count++, 
                    // 外层循环的 i 重置为 内层循环的位置数值
                    // 等待下一个外循环 + 1,继续循环
                    if (judge) {
                        i = k
                        // string = string.slice(k + 1)
                        // i = -1
                        count++
                        A = []
                        break;
                    }
                }
            }
        }
        return count
    };
    
    都读到最后了、留下个建议如何
  • 相关阅读:
    CSS 页面锚点设置
    CSS尺寸 物理像素、CSS像素、dip、dpr、ppi、dpi(一)
    项目代码格式化规范
    Vue 计算属性与监听属性区别
    Python操作InfluxDB
    InfluxDB学习
    Redis学习(五)| 哈希 Hash
    Redis学习(四)| 字符串 String
    Redis学习(三)| 命令、键
    Redis学习(二)| 数据类型
  • 原文地址:https://www.cnblogs.com/linjunfu/p/12638084.html
Copyright © 2011-2022 走看看