【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【回溯】2023C-考古学家【欧弟算法】全网注释最详细分类最全的华为OD真题题解
2023-12-29 18:40:34
题目描述与示例
题目描述
有一个考古学家发现一个石碑,但是很可惜 发现时其已经断成多段,原地发现 N
个断口整齐的石碑碎片,为了破解石碑内容
考古学家希望有程序能帮忙计算复原后的石碑文字,你能帮忙吗
备注
如果存在石碑碎片内容完全相同,则由于碎片间的顺序不影响复原后的碑文内容, 仅相同碎片间的位置变化不影响组合
输入描述
第一行输入 N
,N
表示石碑碎片的个数 第二行依次输入石碑碎片上的文字内容 S
共有 N
组
输出描述
输出石碑文字的组合(按照升序排列),行尾无多余空格
示例一
输入
3
a b c
输出
abc
acb
bac
bca
cab
cba
示例二
输入
3
a b a
输出
aab
aba
baa
示例三
输入
3
a b ab
输出
aabb
abab
abba
baab
baba
解题思路
本题属于排列回溯问题的板子题,和LeetCode47. 全排列II几乎完全一致。
唯一需要注意的是去重,需要多加一个ans_set
哈希表来完成去重操作。
代码
Python
# 题目:2023B-考古学家
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:回溯
# 代码看不懂的地方,请直接在群上提问
# 回溯函数
# words: 单词数组
# ans: 答案数组
# ans_set: 用于判断是否出现重复答案的集合
# path: 当前回溯的路径数组
# used: 判断某元素是否使用过的bool型数组
def dfs(words, ans, ans_set, path, used):
# 递归终止条件:
# 路径长度等于单词数组长度,说明所有单词均被使用
if len(path) == len(words):
path_str = "".join(path)
# 若此时路径在此之前没出现过,则加入ans和ans_set中
if path_str not in ans_set:
ans.append(path_str)
ans_set.add(path_str)
return
# 横向遍历所有单词
for i in range(len(words)):
# 如果单词words[i]已经被使用过,或者和上一个单词相等,则无需再进行回溯,直接跳过
if used[i] or (i > 0 and words[i] == words[i - 1] and not used[i - 1]):
continue
# 状态更新
used[i] = True
path.append(words[i])
# 回溯
dfs(words, ans, ans_set, path, used)
# 回滚
used[i] = False
path.pop()
# 输入数组长度,单词数组
n = int(input())
words = input().split()
# 对words进行从小到大排列
# 这样才能保证组合出来每一个密码都是按升序排序
words.sort()
ans = list()
used = [False] * n
# 递归调用入口
dfs(words, ans, set(), [], used)
# 逐行输出答案
for res in ans:
print(res)
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
String[] words = scanner.nextLine().split(" ");
Arrays.sort(words); // 对单词数组排序
List<String> ans = new ArrayList<>();
boolean[] used = new boolean[n];
dfs(words, ans, new HashSet<>(), new ArrayList<>(), used);
for (String res : ans) {
System.out.println(res);
}
}
public static void dfs(String[] words, List<String> ans, Set<String> ansSet, List<String> path, boolean[] used) {
if (path.size() == words.length) {
String pathStr = String.join("", path);
if (!ansSet.contains(pathStr)) {
ans.add(pathStr);
ansSet.add(pathStr);
}
return;
}
for (int i = 0; i < words.length; i++) {
if (used[i] || (i > 0 && words[i].equals(words[i - 1]) && !used[i - 1])) {
continue;
}
used[i] = true;
path.add(words[i]);
dfs(words, ans, ansSet, path, used);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
C++
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
void dfs(const vector<string>& words, vector<string>& ans, set<string>& ansSet, vector<string>& path, vector<bool>& used);
int main() {
int n;
cin >> n;
vector<string> words(n);
for (int i = 0; i < n; i++) {
cin >> words[i];
}
sort(words.begin(), words.end());
vector<string> ans;
set<string> ansSet;
vector<bool> used(n, false);
vector<string> path;
dfs(words, ans, ansSet, path, used);
for (const string& res : ans) {
cout << res << endl;
}
return 0;
}
void dfs(const vector<string>& words, vector<string>& ans, set<string>& ansSet, vector<string>& path, vector<bool>& used) {
if (path.size() == words.size()) {
string pathStr;
for (const string& str : path) {
pathStr += str;
}
if (ansSet.find(pathStr) == ansSet.end()) {
ans.push_back(pathStr);
ansSet.insert(pathStr);
}
return;
}
for (int i = 0; i < words.size(); i++) {
if (used[i] || (i > 0 && words[i] == words[i - 1] && !used[i - 1])) {
continue;
}
used[i] = true;
path.push_back(words[i]);
dfs(words, ans, ansSet, path, used);
used[i] = false;
path.pop_back();
}
}
时空复杂度
时间复杂度:O(N!)
。
空间复杂度:O(N)
。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336
了解更多
文章来源:https://blog.csdn.net/weixin_48157259/article/details/135295262
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!