A split is called good if you can split s into two non-empty strings
sleft and sright where their concatenation is equal to s (i.e., sleft + sright = s) and the number of distinct letters in sleft and sright is the same.
Return the number ofgood splits you can make in s.
Input: s ="aacaba"Output: 2Explanation: There are 5 ways to split "aacaba" and 2 of them are good.("a","acaba") Left string and right string contains 1 and 3 different letters respectively.("aa","caba") Left string and right string contains 1 and 3 different letters respectively.("aac","aba") Left string and right string contains 2 and 2 different letters respectively(good split).("aaca","ba") Left string and right string contains 2 and 2 different letters respectively(good split).("aacab","a") Left string and right string contains 3 and 1 different letters respectively.
For each split, we need the number of distinct letters in the left and right substrings. We can precompute prefix and suffix distinct counts in O(n) time using two passes.
#include<vector>#include<string>#include<unordered_set>usingnamespace std;
classSolution {
public:int numSplits(string s) {
int n = s.size();
vector<int> left(n), right(n);
unordered_set<char> seen;
for (int i =0; i < n; ++i) {
seen.insert(s[i]);
left[i] = seen.size();
}
seen.clear();
for (int i = n-1; i >=0; --i) {
seen.insert(s[i]);
right[i] = seen.size();
}
int ans =0;
for (int i =0; i < n-1; ++i) {
if (left[i] == right[i+1]) ++ans;
}
return ans;
}
};
import java.util.*;
classSolution {
publicintnumSplits(String s) {
int n = s.length();
int[] left =newint[n], right =newint[n];
Set<Character> seen =new HashSet<>();
for (int i = 0; i < n; ++i) {
seen.add(s.charAt(i));
left[i]= seen.size();
}
seen.clear();
for (int i = n-1; i >= 0; --i) {
seen.add(s.charAt(i));
right[i]= seen.size();
}
int ans = 0;
for (int i = 0; i < n-1; ++i) {
if (left[i]== right[i+1]) ans++;
}
return ans;
}
}
classSolution {
funnumSplits(s: String): Int {
val n = s.length
val left = IntArray(n)
val right = IntArray(n)
val seen = mutableSetOf<Char>()
for (i in0 until n) {
seen.add(s[i])
left[i] = seen.size
}
seen.clear()
for (i in n-1 downTo 0) {
seen.add(s[i])
right[i] = seen.size
}
var ans = 0for (i in0 until n-1) {
if (left[i] == right[i+1]) ans++ }
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution:
defnumSplits(self, s: str) -> int:
n = len(s)
left, right = [0]*n, [0]*n
seen = set()
for i in range(n):
seen.add(s[i])
left[i] = len(seen)
seen.clear()
for i in range(n-1, -1, -1):
seen.add(s[i])
right[i] = len(seen)
ans =0for i in range(n-1):
if left[i] == right[i+1]:
ans +=1return ans
use std::collections::HashSet;
impl Solution {
pubfnnum_splits(s: String) -> i32 {
let n = s.len();
let s = s.as_bytes();
letmut left =vec![0; n];
letmut right =vec![0; n];
letmut seen = HashSet::new();
for i in0..n {
seen.insert(s[i]);
left[i] = seen.len();
}
seen.clear();
for i in (0..n).rev() {
seen.insert(s[i]);
right[i] = seen.len();
}
letmut ans =0;
for i in0..n-1 {
if left[i] == right[i+1] { ans +=1; }
}
ans
}
}