本题出自力扣题库第1525题。题面大意如下:
给定一个字符串s ,一个分割被称为"好分割" 当它满足:将s分割成2个字符串p和q,它们连接起来等于s且p和q中不同字符的数目相同。 返回s中好分割的数目。
示例:
输入:s = "aacaba"
输出:2
解释:总共有 5 种分割字符串 "aacaba" 的方法,其中 2 种是好分割。
("a", "acaba") 左边字符串和右边字符串分别包含 1 个和 3 个不同的字符。
("aa", "caba") 左边字符串和右边字符串分别包含 1 个和 3 个不同的字符。
("aac", "aba") 左边字符串和右边字符串分别包含 2 个和 2 个不同的字符。这是一个好分割。
("aaca", "ba") 左边字符串和右边字符串分别包含 2 个和 2 个不同的字符。这是一个好分割。
("aacab", "a") 左边字符串和右边字符串分别包含 3 个和 1 个不同的字符。
题解:
以长度为5的字符串为例,我们可以得到p和q中不同字符数目的比较关系
p q
s[0:0], s[1:4]
s[0:1], s[2:4]
s[0:2], s[3:4]
s[0:3], s[4:4]
由此,我们使用两个循环来分别计算左右两边的列表,第一个循环按数组下标顺序从小到大,第二个则从大到小,然后依次比较两个对应的数字是否相等即可。
Java代码如下:
import java.util.HashSet;
import java.util.Set;
class Solution {
public int numSplits(String s) {
char[] chars = s.toCharArray();
int N = chars.length;
if (N <= 1) {
return 0;
}
int[] dpLeft = new int[N - 1];
int[] dpRight = new int[N - 1];
Set<Character> leftSet = new HashSet<>();
int count = 0;
for (int i = 0; i < N - 1; i++) {
if (leftSet.add(chars[i])) {
count++;
}
dpLeft[i] = count;
}
Set<Character> rightSet = new HashSet<>();
count = 0;
for (int j = N - 1; j >= 1; j--) {
if (rightSet.add(chars[j])) {
count++;
}
dpRight[j - 1] = count;
}
count = 0;
for (int i = 0; i < N - 1; i++) {
if (dpLeft[i] == dpRight[i]) {
count++;
}
}
return count;
}
}