2025华为OD机试题库(按算法分类):2025华为OD统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)。
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号,火车站只有一个方向进出,同时停靠在火车站的列车中,只有后进站的出站了,先进站的才能出站。
要求输出所有火车出站的方案,以字典序排序输出。
二、输入描述
第一行输入一个正整数N(0 < N <= 10),第二行包括N个正整数,范围为1到10。
三、输出描述
输出以字典序从小到大排序的火车出站序列号,每个编号以空格隔开,每个输出序列换行。
四、测试用例
1、输入
3
1 2 3
2、输出
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
五、解题思路
- 首先通过输入获取火车的数量N和火车入站序列id;
- 创建一个结果集列表,用于存储所有火车出站的方案;
- 创建一个栈,用于模拟火车的进站和出站过程;
- 调用递归函数trainOut,开始计算火车出站的方案;
- 递归函数trainOut的参数包括当前考虑的火车编号i,当前栈的状态s,当前已出站的火车序列str,已出站的火车数量n;
- 如果所有火车均已出站(n等于火车数量N),将当前结果保存到结果集列表中;
- 如果栈非空,表示可以将栈顶火车出栈,将栈顶元素弹出,递归调用trainOut函数,更新已出站的火车序列和数量;
- 将弹出的火车编号加入结果序列str,并加上空格;
- 恢复栈的状态,将弹出的火车编号重新入栈;
- 如果还有未考虑的火车(i小于火车数量N),将下一辆火车入栈,递归调用trainOut函数,更新已出站的火车序列和数量;
- 恢复栈的状态,将最近入栈的火车出栈;
- 最后,对结果集列表进行字典序排序,并依次输出每个出站序列;
六、Python算法源码
# 定义递归函数,生成所有出站序列
def trainOut(id, i, s, sequence, n, results):
# 如果所有火车都已出站,则将当前序列加入结果列表
if n == len(id):
results.append(sequence)
return
# 如果栈不为空,则尝试出站操作
if s:
temp = s.pop() # 弹出栈顶火车
# 递归调用,将该火车加入序列,出站数量加1
trainOut(id, i, s, sequence + str(temp) + " ", n + 1, results)
s.append(temp) # 恢复现场,将火车重新压回栈中
# 如果还有火车未入站,则进行入站操作
if i < len(id):
s.append(id[i]) # 将下一个火车入站(压入栈中)
trainOut(id, i + 1, s, sequence, n, results) # 递归调用,入站索引加1
s.pop() # 恢复现场,移除刚刚入站的火车
# 主函数入口
def main():
import sys # 导入系统模块,用于读取输入
# 读取标准输入所有数据,并按空白字符分割
data = sys.stdin.read().split()
if not data:
return
n = int(data[0]) # 第一项为火车数量
# 后续n项为火车入站序列,转换为整数列表
id = [int(x) for x in data[1:1+n]]
results = [] # 用于保存所有生成的出站序列
s = [] # 用列表模拟栈结构
# 开始递归搜索,初始入站索引为0,已出站火车数为0,初始序列为空
trainOut(id, 0, s, "", 0, results)
results.sort() # 按字典序排序结果
# 输出每个出站序列
for res in results:
print(res)
# 如果作为主程序运行,则调用main函数
if __name__ == '__main__':
main()
七、JavaScript算法源码
// 定义递归函数,生成所有出站序列
function trainOut(id, i, s, sequence, n, results) {
// 如果所有火车都已出站,则将当前序列加入结果数组
if (n === id.length) {
results.push(sequence);
return;
}
// 如果栈不为空,则尝试出站操作
if (s.length > 0) {
let temp = s.pop(); // 弹出栈顶火车
// 递归调用,将该火车加入序列,出站数量加1
trainOut(id, i, s, sequence + temp + " ", n + 1, results);
s.push(temp); // 恢复现场,将火车重新压回栈中
}
// 如果还有火车未入站,则进行入站操作
if (i < id.length) {
s.push(id[i]); // 将下一个火车入站(压入栈中)
trainOut(id, i + 1, s, sequence, n, results); // 递归调用,入站索引加1
s.pop(); // 恢复现场,移除刚刚入站的火车
}
}
// 主函数入口
function main() {
// 读取标准输入(使用fs模块同步读取)
let input = require('fs').readFileSync(0, 'utf-8').trim().split(/\s+/);
if (input.length === 0) return;
let n = parseInt(input[0]); // 第一项为火车数量
let id = []; // 用于保存火车入站序列
// 将后续n项转换为整数并存入数组
for (let i = 0; i < n; i++) {
id.push(parseInt(input[i + 1]));
}
let results = []; // 保存所有出站序列
let s = []; // 用数组模拟栈
// 开始递归搜索,初始入站索引为0,出站数为0,序列为空
trainOut(id, 0, s, "", 0, results);
results.sort(); // 按字典序排序
// 输出每个出站序列,每行一个
results.forEach(line => {
console.log(line);
});
}
// 调用主函数
main();
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SOL 10000 // 假设最多10000个序列
#define MAX_LEN 50 // 每个序列的最大字符长度
// 全局数组用于存储所有出站序列
char* solutions[MAX_SOL];
int solCount = 0; // 当前存储的序列数量
// 交换两个字符串指针(用于qsort排序)
int cmp(const void *a, const void *b) {
return strcmp(*(char **)a, *(char **)b);
}
/*
* 递归函数,生成所有出站序列
* id: 输入火车序列数组
* n: 火车数量
* i: 当前入站火车索引
* s: 用数组模拟的栈,保存当前站内火车
* top: 栈顶指针(当前栈中元素个数)
* seq: 当前形成的出站序列字符串
* seqLen: 当前字符串长度
*/
void trainOut(int id[], int n, int i, int s[], int top, char seq[], int seqLen) {
// 如果所有火车都已出站,则将当前序列保存
if (seqLen >= 0 && seqLen > 0 && solCount < MAX_SOL && (seqLen - 1) >= 0) {
// 当出站火车数量等于n时,seq中已经有n个数字(以及空格)
if ((seqLen - 1) / 2 == n) {
seq[seqLen] = '\0'; // 结束字符串
solutions[solCount] = (char*)malloc((seqLen + 1) * sizeof(char));
strcpy(solutions[solCount], seq);
solCount++;
return;
}
}
// 如果栈非空,则尝试出站操作
if (top > 0) {
int temp = s[top - 1]; // 获取栈顶元素
top--; // 出栈
// 记录出站操作,将数字及空格加入seq中
int len = sprintf(seq + seqLen, "%d ", temp);
trainOut(id, n, i, s, top, seq, seqLen + len);
// 回溯恢复现场:撤销添加的数字
seqLen -= len;
seq[seqLen] = '\0';
s[top] = temp; // 将火车压回栈中
top++;
}
// 如果还有火车未入站,则进行入站操作
if (i < n) {
s[top] = id[i]; // 将火车入栈
trainOut(id, n, i + 1, s, top + 1, seq, seqLen);
// 回溯:不需要显式出栈,因下次覆盖即可
}
}
int main() {
int n;
// 读取火车数量
if (scanf("%d", &n) != 1) return 1;
int *id = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
scanf("%d", &id[i]); // 读取每辆火车编号
}
int s[20]; // 栈数组(n<=10,预留足够空间)
char seq[MAX_LEN] = ""; // 存储当前出站序列字符串
solCount = 0; // 初始化结果计数
// 开始递归搜索,初始入站索引为0,栈空,序列长度0
trainOut(id, n, 0, s, 0, seq, 0);
// 对结果进行字典序排序
qsort(solutions, solCount, sizeof(char*), cmp);
// 输出所有序列
for (int i = 0; i < solCount; i++) {
printf("%s\n", solutions[i]);
free(solutions[i]); // 释放内存
}
free(id); // 释放输入数组内存
return 0;
}
九、C++算法源码
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
// 全局变量,用于存储所有出站序列
vector<string> results;
/*
* 递归函数,生成所有出站序列
* id: 输入火车序列(vector<int>)
* i: 当前入站火车的索引
* s: 用stack<int>模拟火车站
* seq: 当前已形成的出站序列字符串
* n: 当前已出站火车的数量
*/
void trainOut(const vector<int>& id, int i, stack<int>& s, string seq, int n) {
if(n == id.size()) { // 当所有火车均出站
results.push_back(seq); // 保存当前序列
return;
}
// 如果栈不为空,则进行出站操作
if(!s.empty()) {
int temp = s.top(); // 获取栈顶火车
s.pop(); // 执行出站操作
trainOut(id, i, s, seq + to_string(temp) + " ", n + 1); // 递归调用
s.push(temp); // 回溯恢复现场
}
// 如果还有火车未入站,则进行入站操作
if(i < id.size()) {
s.push(id[i]); // 将下一辆火车入站
trainOut(id, i + 1, s, seq, n); // 递归调用,入站索引增加
s.pop(); // 回溯恢复现场
}
}
int main() {
int n;
cin >> n; // 读取火车数量
vector<int> id(n);
for (int i = 0; i < n; i++) {
cin >> id[i]; // 读取每辆火车的编号
}
stack<int> s; // 用于模拟火车站的栈
trainOut(id, 0, s, "", 0); // 开始递归搜索
sort(results.begin(), results.end()); // 按字典序排序结果
// 输出所有出站序列
for (const auto& str : results) {
cout << str << endl;
}
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。