【每日一题记录】1422. 分割字符串的最大得分

135 阅读1分钟

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

大家好 我是短袖撸码蒂尔尼。今天带来的是一道在LeetCode上的题目,题目难度不大。但我好久没做过这种题目了并且最近在进行代码题复习,就在此为大家分享一下解答思路。

题目阐述

题目在这里

给你一个由若干 0 和 1 组成的字符串 s ,请你计算并返回将该字符串分割成两个 非空 子字符串(即 左 子字符串和 右 子字符串)所能获得的最大得分。

「分割字符串的得分」为 左 子字符串中 0 的数量加上 右 子字符串中 1 的数量。

输入:s = "011101"
输出:5 
解释:
将字符串 s 划分为两个非空子字符串的可行方案有:
左子字符串 = "0" 且 右子字符串 = "11101",得分 = 1 + 4 = 5 
左子字符串 = "01" 且 右子字符串 = "1101",得分 = 1 + 3 = 4 
左子字符串 = "011" 且 右子字符串 = "101",得分 = 1 + 2 = 3 
左子字符串 = "0111" 且 右子字符串 = "01",得分 = 1 + 1 = 2 
左子字符串 = "01110" 且 右子字符串 = "1",得分 = 2 + 1 = 3

提示:

  • 2 <= s.length <= 500
  • 字符串 s 仅由字符 '0' 和 '1' 组成。

思路阐述

我的思路比较直接,就是

  • 遍历
  • 定义两个函数getLeftScoregetRightScore分别结算这左边和右边两个子字符串的得分
var maxScore = function(charArray) {
    max=0
    score=0
    for (let i=1;i<charArray.length;i++){
        left=getLeftScore(charArray.slice(0,i))
        right=getRightScore(charArray.slice(i,i.length))
        max=left+right>max?left+right:max
    }
    return max
};
getLeftScore=(str)=>{
    score=0
    for (let i=0;i<str.length;i++)
        score+=Number(str[i]=='0')
    return score
}
getRightScore=(str)=>{
    score=0
    for (let i=0;i<str.length;i++)
        score+=Number(str[i])
    return score
}

容易猜的坑

  • 题目已经说了 2 <= s.length <= 500 我还傻乎乎的写了if(s.length<2) return Number(s) 这种代码 捂脸
  • 注意的是原题目里的子字符串的最小长度为1 因此在遍历的时候 i从1开始遍历。

提交成绩

image.png

这个成绩相当一般,那么有什么更好的解法呢?

其他优秀解法分享

看了一遍题解,我发现了一个更加巧妙的解题思路:

一次遍历就过 via 宫水三叶

利用S只有0和1 每当S[i]=0的时候 说明有一个 0从右串中移到了左串,并且 0 在右串中不得分,在左串中得分,因此总得分加一。 而S[i]=1的时候,说明有一个 11 从右串中移到了左串,而 11 在右串中得分,在左串中不得分,因此总得分减一。在所有得分中取最大值即是答案。

function maxScore(s: string): number {
    let n = s.length, cur = s[0] == '0' ? 1 : 0
    for (let i = 1; i < n; i++) cur += s[i] == '1' ? 1 : 0
    let ans = cur
    for (let i = 1; i < n - 1; i++) {
        cur += s[i] == '0' ? 1 : -1
        ans = Math.max(ans, cur)
    }
    return ans
};

个人的评价是很巧妙,利用一次遍历就可以计算出得分值,跳出了常规的遍历思路。

我是短袖撸码蒂尔尼
一名热爱阿森纳的前端工程师
如果本文对您有帮助,可以给一个免费的赞吗?谢谢!

名片.jpg