LeetCode 1422. 分割字符串的最大得分
一、题目
题目描述
给你一个由若干 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
二、题目分析
字符串至少拆分成两部分,计算左部的 0的个数与右部 1的个数求和,遍历字符串到结束,求最大的和。
三、题解
方法一
暴力枚举法
用 n 表示字符串 s 的长度。i 是一个分割点,将字符串 s 分割成两个非空子字符串,左子字符串的下标范围是 [0, i - 1],右子字符串的下标范围是 [i, n - 1],分别计算左子字符串中的 0 的个数和右子字符串中的 1 的个数即可得到分割字符串的得分。遍历所有的分割点,即可得到分割字符串的最大得分。
双重 for 循环,外层循环指针控制分割字符串的位置,内部 for 循环求解和,每次保留最大值,外层循环结束,返回结果
public int maxScore(String s) {
int maxSco = 0;
for(int i = 1; i < s.length(); i++){
int score = 0;
for(int j = 0; j < i; j++){
if(s.charAt(j) == '0'){
score++;
}
}
for(int k = i; k < s.length(); k++){
if(s.charAt(k) == '1'){
score++;
}
}
maxSco = Math.max(maxSco,score);
}
return maxSco;
}
时间复杂度:O(n^2)
空间复杂度:O(1)
方法二
初始化最开始分字符串分割,求出和。再次遍历字符串,注意剩余 最开始 和 最结尾的,因为至少要拆分成两个字符串序列。每次保留最大值,进行返回即可。
public int maxScore(String s) {
// 单次循环,两次遍历
// 以第一个字符拆分,求score 作为初始值,从第一个遍历,遇 0 + 1,遇 1 - 1
int score = 0;
if(s.charAt(0) == '0'){
score++;
}
for(int i = 1; i < s.length(); i++){
if(s.charAt(i) == '1'){
score++;
}
}
int res = score;
// 注意 左右至少留一个
for(int i = 1; i < s.length() - 1; i++){
if(s.charAt(i) == '1'){
score--;
}else{
score++;
}
res = Math.max(score,res);
}
return res;
}
时间复杂度:O(n)
空间复杂度:O(1)