华为OD机试统一考试D卷C卷 - 构成指定长度字符串的个数
OD统一考试(C卷)
分值: 100分
题解: Java / Python / C++
题目描述:构成指定长度字符串的个数 (本题分值100)
给定 M(0 < M ≤ 30)个字符(a-z),从中取出任意字符(每个字符只能用一次)拼接成长度为 N(0 < N ≤ 5)的字符串,
要求相同的字符不能相邻,计算出给定的字符列表能拼接出多少种满足条件的字符串,
输入非法或者无法拼接出满足条件的字符串则返回0。
输入描述
给定的字符列表和结果字符串长度,中间使用空格(" ")拼接
输出描述
满足条件的字符串个数
用例1
输入
aab 2
输出
2
说明
只能构成ab,ba。
用例2
输入
abc 2
输出
6
说明
可以构成:ab ac ba bc ca cb 。
解题思路
使用递归和回溯的思想来生成不同的字符串。具体的逻辑如下:
- 首先,我们定义一个函数generateDistinctStrings,这个函数接收以下参数:可用字符集s,目标字符串长度length,当前已生成的字符串current,已生成的结果集result,以及一个标记数组used,用来记录每个字符是否已被使用。
- 在generateDistinctStrings函数中,首先检查当前已生成的字符串current的长度是否等于目标长度length。如果等于,说明我们已经生成了一个满足长度要求的字符串,将其添加到结果集result中,然后返回。
- 如果当前字符串current的长度还未达到目标长度length,我们就需要继续添加字符。此时,我们遍历可用字符集s中的每一个字符。对于每一个字符,我们首先检查它是否已经被使用(通过查看used数组),以及它是否与current的最后一个字符相同。如果字符已经被使用,或者与current的最后一个字符相同,我们就跳过这个字符,继续检查下一个字符。
- 如果一个字符未被使用,且与current的最后一个字符不同,我们就将它添加到current的末尾,然后标记这个字符为已使用,接着递归调用generateDistinctStrings函数,以生成下一个字符。
- 在递归调用返回后,我们需要取消对当前字符的使用标记,以便在后续的遍历中可以再次使用这个字符。这就是回溯的思想,即撤销之前的选择,尝试其他的选择。
以下是对应的中文伪代码:
函数 generateDistinctStrings(s, length, current, result, used) 如果 current的长度 等于 length 将 current 添加到 result 返回 对于 s中的每一个字符 c 如果 c已被使用 或者 c与current的最后一个字符相同 继续下一次循环 标记 c为已使用 generateDistinctStrings(s, length, current + c, result, used) 取消标记 c的使用状态
C++
#include <iostream> #include <unordered_set> #include <vector> #include <sstream> using namespace std; // 递归生成满足条件的不同字符串 void generateDistinctStrings(string s, int length, string current, unordered_set<string>& result, vector<bool>& used) { // 当生成的字符串长度等于指定长度时,将其加入到结果集中 if (current.length() == length) { result.insert(current); return; } // 遍历字符串中的字符 for (int i = 0; i < s.length(); i++) { // 判断字符是否已经被使用,或者当前字符与前一个字符相同 if (used[i] || (current.length() > 0 && current.back() == s[i])) { continue; // 如果字符已被使用或与前一个字符相同,则跳过当前字符 } used[i] = true; // 标记当前字符为已使用 // 递归调用生成下一个字符 generateDistinctStrings(s, length, current + s[i], result, used); used[i] = false; // 取消标记当前字符的使用状态,以便下一次遍历 } } // 计算满足条件的不同字符串的数量 int countDistinctStrings(string s, int length) { // 创建一个集合来存储不同的字符串 unordered_set<string> distinctStrings; // 创建一个列表来标记字符串中的字符是否已经被使用 vector<bool> used(s.length(), false); // 调用generateDistinctStrings方法生成满足条件的不同字符串 generateDistinctStrings(s, length, "", distinctStrings, used); // 打印生成的所有不同的字符串 // for (auto& str : distinctStrings) { // cout << str << endl; // } // 返回不同字符串的数量 return distinctStrings.size(); } int main() { string input; getline(cin, input); // 将输入的字符串按空格分割为两部分,分别为字符串和长度 string str; int length; istringstream iss(input); iss >> str >> length; // 调用countDistinctStrings方法计算满足条件的不同字符串的数量 int count = countDistinctStrings(str, length); // 输出计算结果 cout << count << endl; return 0; }
Java
import java.util.*; public class Main { public static void main(String[] args) { // 创建一个Scanner对象来读取用户的输入 Scanner sc = new Scanner(System.in); // 读取用户输入的字符串 String input = sc.nextLine(); // 将输入的字符串按空格分割为两部分,分别为字符串和长度 String[] parts = input.split(" "); String str = parts[0]; // 获取输入的字符串 int length = Integer.parseInt(parts[1]); // 将输入的长度部分转换为整数 // 调用countDistinctStrings方法计算满足条件的不同字符串的数量 int count = countDistinctStrings(str, length); // 输出计算结果 System.out.println(count); } // 计算满足条件的不同字符串的数量 public static int countDistinctStrings(String str, int length) { // 创建一个HashSet来存储不同的字符串 HashSet<String> set = new HashSet<>();
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
机试E卷D卷刷题日记 文章被收录于专栏
机试刷题记录