Overflow in intermediate arithmetic
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Move from brute-force thinking to an efficient approach using math strategy.
Given a binary string s, you can split s into 3 non-empty strings s1, s2, and s3 where s1 + s2 + s3 = s.
Return the number of ways s can be split such that the number of ones is the same in s1, s2, and s3. Since the answer may be too large, return it modulo 109 + 7.
Example 1:
Input: s = "10101" Output: 4 Explanation: There are four ways to split s in 3 parts where each part contain the same number of letters '1'. "1|010|1" "1|01|01" "10|10|1" "10|1|01"
Example 2:
Input: s = "1001" Output: 0
Example 3:
Input: s = "0000" Output: 3 Explanation: There are three ways to split s in 3 parts. "0|0|00" "0|00|0" "00|0|0"
Constraints:
3 <= s.length <= 105s[i] is either '0' or '1'.Problem summary: Given a binary string s, you can split s into 3 non-empty strings s1, s2, and s3 where s1 + s2 + s3 = s. Return the number of ways s can be split such that the number of ones is the same in s1, s2, and s3. Since the answer may be too large, return it modulo 109 + 7.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Math
"10101"
"1001"
"0000"
split-array-with-equal-sum)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1573: Number of Ways to Split a String
class Solution {
private String s;
public int numWays(String s) {
this.s = s;
int cnt = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
if (s.charAt(i) == '1') {
++cnt;
}
}
int m = cnt % 3;
if (m != 0) {
return 0;
}
final int mod = (int) 1e9 + 7;
if (cnt == 0) {
return (int) (((n - 1L) * (n - 2) / 2) % mod);
}
cnt /= 3;
long i1 = find(cnt), i2 = find(cnt + 1);
long j1 = find(cnt * 2), j2 = find(cnt * 2 + 1);
return (int) ((i2 - i1) * (j2 - j1) % mod);
}
private int find(int x) {
int t = 0;
for (int i = 0;; ++i) {
t += s.charAt(i) == '1' ? 1 : 0;
if (t == x) {
return i;
}
}
}
}
// Accepted solution for LeetCode #1573: Number of Ways to Split a String
func numWays(s string) int {
cnt := 0
for _, c := range s {
if c == '1' {
cnt++
}
}
m := cnt % 3
if m != 0 {
return 0
}
const mod = 1e9 + 7
n := len(s)
if cnt == 0 {
return (n - 1) * (n - 2) / 2 % mod
}
cnt /= 3
find := func(x int) int {
t := 0
for i := 0; ; i++ {
if s[i] == '1' {
t++
if t == x {
return i
}
}
}
}
i1, i2 := find(cnt), find(cnt+1)
j1, j2 := find(cnt*2), find(cnt*2+1)
return (i2 - i1) * (j2 - j1) % mod
}
# Accepted solution for LeetCode #1573: Number of Ways to Split a String
class Solution:
def numWays(self, s: str) -> int:
def find(x):
t = 0
for i, c in enumerate(s):
t += int(c == '1')
if t == x:
return i
cnt, m = divmod(sum(c == '1' for c in s), 3)
if m:
return 0
n = len(s)
mod = 10**9 + 7
if cnt == 0:
return ((n - 1) * (n - 2) // 2) % mod
i1, i2 = find(cnt), find(cnt + 1)
j1, j2 = find(cnt * 2), find(cnt * 2 + 1)
return (i2 - i1) * (j2 - j1) % (10**9 + 7)
// Accepted solution for LeetCode #1573: Number of Ways to Split a String
struct Solution;
const MOD: i64 = 1_000_000_007;
impl Solution {
fn num_ways(s: String) -> i32 {
let n = s.len();
let s: Vec<i32> = s.chars().map(|c| if c == '1' { 1 } else { 0 }).collect();
let m: i32 = s.iter().sum();
if m == 0 {
return (((n - 1) as i64 * (n - 2) as i64) / 2 % MOD) as i32;
}
if m % 3 != 0 {
return 0;
}
let mut indexes = vec![];
let k = m / 3;
let mut sum = 0;
for i in 0..n {
if s[i] == 1 && sum % k == 0 {
indexes.push(i);
}
sum += s[i];
if s[i] == 1 && sum % k == 0 {
indexes.push(i);
}
}
(((indexes[2] - indexes[1]) as i64 * (indexes[4] - indexes[3]) as i64) % MOD) as i32
}
}
#[test]
fn test() {
let s = "10101".to_string();
let res = 4;
assert_eq!(Solution::num_ways(s), res);
let s = "1001".to_string();
let res = 0;
assert_eq!(Solution::num_ways(s), res);
let s = "0000".to_string();
let res = 3;
assert_eq!(Solution::num_ways(s), res);
let s = "100100010100110".to_string();
let res = 12;
assert_eq!(Solution::num_ways(s), res);
}
// Accepted solution for LeetCode #1573: Number of Ways to Split a String
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #1573: Number of Ways to Split a String
// class Solution {
// private String s;
//
// public int numWays(String s) {
// this.s = s;
// int cnt = 0;
// int n = s.length();
// for (int i = 0; i < n; ++i) {
// if (s.charAt(i) == '1') {
// ++cnt;
// }
// }
// int m = cnt % 3;
// if (m != 0) {
// return 0;
// }
// final int mod = (int) 1e9 + 7;
// if (cnt == 0) {
// return (int) (((n - 1L) * (n - 2) / 2) % mod);
// }
// cnt /= 3;
// long i1 = find(cnt), i2 = find(cnt + 1);
// long j1 = find(cnt * 2), j2 = find(cnt * 2 + 1);
// return (int) ((i2 - i1) * (j2 - j1) % mod);
// }
//
// private int find(int x) {
// int t = 0;
// for (int i = 0;; ++i) {
// t += s.charAt(i) == '1' ? 1 : 0;
// if (t == x) {
// return i;
// }
// }
// }
// }
Use this to step through a reusable interview workflow for this problem.
Simulate the process step by step — multiply n times, check each number up to n, or iterate through all possibilities. Each step is O(1), but doing it n times gives O(n). No extra space needed since we just track running state.
Math problems often have a closed-form or O(log n) solution hidden behind an O(n) simulation. Modular arithmetic, fast exponentiation (repeated squaring), GCD (Euclidean algorithm), and number theory properties can dramatically reduce complexity.
Review these before coding to avoid predictable interview regressions.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.