华为OD机试 - 万能字符单词拼写(Java & JS & Python & C & C++)
题目描述:
给定一个字符串s,请你找出一个字符串t,使得t是s的一个子序列且由字符"a"、"b"、"c"三种字符构成,且必须满足下列条件:
- "a" 只能在 "b" 前面;
- "b" 只能在 "c" 前面;
- 每种字符在t中出现的次数不超过s中该字符出现的次数。
请你输出满足条件的t的数量。
注意:子序列不一定需要连续。
输入描述:
输入为一行字符串s,只包含"a"、"b"、"c"三种字符。
输出描述:
输出一个整数,表示满足条件的t的数量。
示例:
输入:"abb"
输出:2
解释:满足条件的t有"a","ab","ac","bc"。
解题思路:
这是一个动态规划问题。我们可以定义一个三维数组dp,其中dp[i][j][k]表示s[0..i]中选择字符'a'j次,'b'k次的方案数。
状态转移方程为:
- 如果s[i] == 'a',dp[i][j][k] = dp[i-1][j-1][k]
- 如果s[i] == 'b',dp[i][j][k] = dp[i-1][j][k-1]
- 如果s[i] == 'c',dp[i][j][k] = dp[i-1][j][k]
初始化:dp[0][0][0] = 1。
最终的答案是dp[s.length()-1][a\_count][b\_count],其中a\_count和b\_count分别是s中'a'和'b'的数量。
代码实现:
Java版本:
public class Main {
public static void main(String[] args) {
String s = "abb";
System.out.println(countValidT(s));
}
public static int countValidT(String s) {
int[] aCount = {0, 0};
int[] bCount = {0, 0};
char[] chars = s.toCharArray();
for (char c : chars) {
if (c == 'a') {
aCount[0]++;
} else if (c == 'b') {
aCount[1]++;
} else {
bCount[1]++;
}
}
return dp(chars.length, aCount[0], bCount[0]);
}
public static int dp(int n, int aCount, int bCount) {
int[][][] dp = new int[n][aCount + 1][bCount + 1];
dp[0][0][0] = 1;
for (int i = 0; i < n; i++) {
char c = i < n ? (char) ('a' + (int) (Math.random() * 3)) : 'c';
for (int j = 0; j <= aCount; j++) {
for (int k = 0; k <= bCount; k++) {
if (c == 'a') {
if (j - 1 >= 0) {
dp[i][j][k] += dp[i - 1][j - 1][k];
}
} else if (c == 'b') {
if (k - 1 >= 0) {
dp[i][j][k] += dp[i - 1][j][k - 1];
}
} else {
dp[i][j][k] += dp[i - 1][j][k];
}
评论已关闭