携手创作,共同成长!这是我参与「掘金日新计划 · 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'组成。
思路阐述
我的思路比较直接,就是
- 遍历
- 定义两个函数getLeftScore和getRightScore分别结算这左边和右边两个子字符串的得分
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开始遍历。
提交成绩
这个成绩相当一般,那么有什么更好的解法呢?
其他优秀解法分享
看了一遍题解,我发现了一个更加巧妙的解题思路:
一次遍历就过 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
};
个人的评价是很巧妙,利用一次遍历就可以计算出得分值,跳出了常规的遍历思路。
我是短袖撸码蒂尔尼
一名热爱阿森纳的前端工程师
如果本文对您有帮助,可以给一个免费的赞吗?谢谢!