1422. Maximum Score After Splitting a String - Explanation
Description
You are given a string s of zeros and ones, return the maximum score after splitting the string into two non-empty substrings (i.e. left substring and right substring).
The score after splitting a string is the number of zeros in the left substring plus the number of ones in the right substring.
Example 1:
Input: s = "011101"
Output: 5Explanation: All possible ways of splitting s into two non-empty substrings are:
left = "0" and right = "11101", score = 1 + 4 = 5
left = "01" and right = "1101", score = 1 + 3 = 4
left = "011" and right = "101", score = 1 + 2 = 3
left = "0111" and right = "01", score = 1 + 1 = 2
left = "01110" and right = "1", score = 2 + 1 = 3
Example 2:
Input: s = "00111"
Output: 5Example 3:
Input: s = "1111"
Output: 3Constraints:
2 <= s.length <= 500sconsists of characters'0'and'1'only.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Prefix Sums - Precomputing cumulative counts to enable O(1) lookups for range queries
- String Traversal - Iterating through a string while maintaining running counts of characters
- Algebraic Optimization - Reformulating the score formula to reduce the problem to a single-pass solution
1. Brute Force
Intuition
The score at any split point is the sum of zeros in the left substring plus the sum of ones in the right substring. The simplest approach is to try every valid split position and count directly. For each split, we scan the left portion to count zeros and the right portion to count ones, then track the maximum score found.
Algorithm
- Iterate through each valid split position
ifrom index1ton-1(both substrings must be non-empty). - For each split position:
- Count zeros in the left substring (indices
0toi-1). - Count ones in the right substring (indices
iton-1). - Calculate the score as the sum of these two counts.
- Count zeros in the left substring (indices
- Track and return the maximum score across all split positions.
class Solution:
def maxScore(self, s: str) -> int:
n, res = len(s), 0
for i in range(1, n):
left_zero = 0
for j in range(i):
if s[j] == '0':
left_zero += 1
right_one = 0
for j in range(i, n):
if s[j] == '1':
right_one += 1
res = max(res, left_zero + right_one)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
2. Prefix & Suffix Arrays
Intuition
Instead of recounting zeros and ones for every split position, we can precompute cumulative counts. A prefix array stores the count of zeros up to each index, while a suffix array stores the count of ones from each index to the end. This way, evaluating any split becomes an O(1) lookup.
Algorithm
- Build a prefix array
left_zerowhereleft_zero[i]holds the count of zeros from index0toi. - Build a suffix array
right_onewhereright_one[i]holds the count of ones from indexiton-1. - For each valid split position
i(from1ton-1):- The score is
left_zero[i-1] + right_one[i].
- The score is
- Return the maximum score found.
class Solution:
def maxScore(self, s: str) -> int:
n = len(s)
left_zero = [0] * n
right_one = [0] * n
if s[0] == '0':
left_zero[0] = 1
for i in range(1, n):
left_zero[i] = left_zero[i - 1]
if s[i] == '0':
left_zero[i] += 1
if s[n - 1] == '1':
right_one[n - 1] = 1
for i in range(n - 2, -1, -1):
right_one[i] = right_one[i + 1]
if s[i] == '1':
right_one[i] += 1
res = 0
for i in range(1, n):
res = max(res, left_zero[i - 1] + right_one[i])
return resTime & Space Complexity
- Time complexity:
- Space complexity:
3. Iteration (Two Pass)
Intuition
We can avoid storing full arrays by maintaining running counts. First, count all ones in the string. Then iterate through the string, incrementing zeros and decrementing ones as we move the split point. At each position, the current counts represent exactly what we need for the score calculation.
Algorithm
- Count the total number of ones in the string.
- Initialize
zero = 0to track zeros seen so far. - Iterate from index
0ton-2(last valid split position):- If the current character is
'0', incrementzero. - Otherwise, decrement
one(this one moves from right to left portion). - Update the result with
zero + one.
- If the current character is
- Return the maximum score.
Time & Space Complexity
- Time complexity:
- Space complexity:
4. Iteration (One Pass)
Intuition
We can derive a single-pass solution using algebra. The score at position i equals left_zeros + right_ones. Since right_ones = total_ones - left_ones, the score becomes left_zeros + total_ones - left_ones, or equivalently total_ones + (left_zeros - left_ones). Since total_ones is constant, we only need to maximize (left_zeros - left_ones) while iterating, then add the total ones at the end.
Algorithm
- Process the first character to initialize
zerosandonescounters. - Iterate from index
1ton-1:- Update the maximum of
(zeros - ones)before processing the current character. - Update counters based on whether the current character is
'0'or'1'.
- Update the maximum of
- Return
result + ones(whereonesnow contains the total count).
class Solution:
def maxScore(self, s: str) -> int:
# res = Max of all (left_zeros + right_ones)
# res = Max of all (left_zeros + (total_ones - left_ones))
# res = total_ones (constant) + Max of all (left_zeros - left_ones)
zeros = 0
ones = 0
if s[0] == '0':
zeros += 1
else:
ones += 1
res = float('-inf')
for i in range(1, len(s)):
res = max(res, zeros - ones)
if s[i] == '0':
zeros += 1
else:
ones += 1
return res + onesTime & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Allowing Empty Substrings
The problem requires both left and right substrings to be non-empty. Splitting at index 0 (empty left) or index n (empty right) is invalid. The loop should iterate from index 1 to n-1, not from 0 to n. Forgetting this constraint leads to incorrect boundary cases.
Counting Characters in the Wrong Substring
When computing the score, zeros should be counted in the left substring only, and ones should be counted in the right substring only. A common mistake is counting ones on the left or zeros on the right, which inverts the logic and produces wrong results.
Sign in to join the discussion