LeetCode 1221: Split a String in Balanced Strings (Greedy Balance Counter)
LeetCode 1221StringGreedyToday we solve LeetCode 1221 - Split a String in Balanced Strings.
Source: https://leetcode.com/problems/split-a-string-in-balanced-strings/
English
Problem Summary
Given a string s containing only 'L' and 'R', split it into the maximum number of non-empty balanced substrings, where each substring has the same number of L and R.
Key Insight
Use a running balance: add +1 for L, and -1 for R. Whenever balance becomes 0, one balanced substring is completed. Greedily splitting at every zero is optimal because delaying a valid split cannot increase total pieces.
Algorithm
- Initialize balance = 0, answer = 0.
- Traverse each character:
• if char is L, balance++; else balance--.
• if balance == 0, increment answer.
- Return answer.
Complexity Analysis
Time: O(n), where n is the length of s.
Space: O(1).
Common Pitfalls
- Trying to use nested loops unnecessarily.
- Forgetting this is a maximum split problem, so count every time balance hits zero.
- Reversing the sign convention is okay, but keep it consistent.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int balancedStringSplit(String s) {
int balance = 0;
int answer = 0;
for (int i = 0; i < s.length(); i++) {
balance += (s.charAt(i) == 'L') ? 1 : -1;
if (balance == 0) {
answer++;
}
}
return answer;
}
}func balancedStringSplit(s string) int {
balance, answer := 0, 0
for _, ch := range s {
if ch == 'L' {
balance++
} else {
balance--
}
if balance == 0 {
answer++
}
}
return answer
}class Solution {
public:
int balancedStringSplit(string s) {
int balance = 0, answer = 0;
for (char c : s) {
balance += (c == 'L') ? 1 : -1;
if (balance == 0) {
answer++;
}
}
return answer;
}
};class Solution:
def balancedStringSplit(self, s: str) -> int:
balance = 0
answer = 0
for ch in s:
balance += 1 if ch == 'L' else -1
if balance == 0:
answer += 1
return answervar balancedStringSplit = function(s) {
let balance = 0;
let answer = 0;
for (const ch of s) {
balance += (ch === 'L') ? 1 : -1;
if (balance === 0) {
answer++;
}
}
return answer;
};中文
题目概述
给定只包含 'L' 和 'R' 的字符串 s,要把它切分成尽可能多的非空平衡子串。平衡子串指的是其中 L 与 R 数量相同。
核心思路
用一个平衡计数器:遇到 L 就 +1,遇到 R 就 -1。当计数器回到 0 时,说明当前这一段已经平衡,可以立即切一刀并计数。每次回到 0 都切分,能保证子串数量最大。
算法步骤
- 初始化 balance = 0、answer = 0。
- 遍历字符串每个字符:
• 若为 L,balance++;否则 balance--。
• 若 balance == 0,说明形成一个平衡子串,answer++。
- 最终返回 answer。
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(1)。
常见陷阱
- 没必要双层循环暴力尝试切分。
- 忘记在每次 balance == 0 时立刻计数,导致答案变小。
- L/R 的加减定义可互换,但整段逻辑必须保持一致。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int balancedStringSplit(String s) {
int balance = 0;
int answer = 0;
for (int i = 0; i < s.length(); i++) {
balance += (s.charAt(i) == 'L') ? 1 : -1;
if (balance == 0) {
answer++;
}
}
return answer;
}
}func balancedStringSplit(s string) int {
balance, answer := 0, 0
for _, ch := range s {
if ch == 'L' {
balance++
} else {
balance--
}
if balance == 0 {
answer++
}
}
return answer
}class Solution {
public:
int balancedStringSplit(string s) {
int balance = 0, answer = 0;
for (char c : s) {
balance += (c == 'L') ? 1 : -1;
if (balance == 0) {
answer++;
}
}
return answer;
}
};class Solution:
def balancedStringSplit(self, s: str) -> int:
balance = 0
answer = 0
for ch in s:
balance += 1 if ch == 'L' else -1
if balance == 0:
answer += 1
return answervar balancedStringSplit = function(s) {
let balance = 0;
let answer = 0;
for (const ch of s) {
balance += (ch === 'L') ? 1 : -1;
if (balance === 0) {
answer++;
}
}
return answer;
};
Comments