华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
将一个csv格式的数据文件Q中包含有单元格引用的内容替换为对应单元格内容的实际值。
Comma seprated values (CSV) 逗号分隔值,csv格式的数据文件使用逗号作为分隔符Q将各单元格的内容进行分隔。
二、输入描述
- 输入只有一行数据, 用逗号分隔每个单元格, 行尾没有逗号。最多26个单元格, 对应编号A-Z。
- 每个单元格的内容包含字母和数字,以及使用<>分隔的单元格引用,例如: 表示引用第一个单元格的值。
- 每个单元格的内容, 在替换前和替换后均不超过100个字符。
- 引用单元格的位置不受限制, 运行排在后面的单元格被排在前面的单元格引用。
- 不存在循环引用的情况, 比如下面这种场景是不存在的:
A单元格:aCd8u
B单元格:kAydzqo - 不存在多重<>的情况, 一个单元格只能引用一个其他单元格。比如下面这种场景是不存在的:
- A单元格:aCd8u
- B单元格:kAydzqo
- C单元格:y<>d
三、输出描述
输出所有单元格展开的内容, 单元格之间用逗号分隔。处理过程中出现错误时, 输出字符串Q "-1"表示出错。
四、测试用例
测试用例1:
1、输入
1,200
2、输出
1,2100
3、说明
第二个单元中有对A单元的引用,A单元格的值为1,替换时,将A单元的内容替代的位置,并和其他内容合并。
测试用例2:
1、输入
12,1
2、输出
112,1
3、说明
第一个单元中有对B单元的引用,B单元格的值为1,替换时,将第二个数据单元的内容替代的位置,并和其他内容合并。
五、解题思路
1、为什么采用递归?
这是基于分治思想的一个简单递归,每次将当前的引用替换为实际内容,然后继续递归解析被引用的单元格,直到没有引用为止。
如果发现某个单元格引用了其他单元格,使用递归调用 resolveReference() 方法来解析引用的单元格内容。
递归确保了即使一个单元格引用了多个层次的单元格(如 A 引用 B,B 引用 C),最终都能解析到实际内容。
2、具体步骤:
- 解析输入:
- 将输入的CSV数据按照逗号分割成一个字符串数组,每个字符串代表一个单元格的内容。根据题意,最多有26个单元格,对应A-Z。
- 查找并替换引用:
- 对每个单元格的内容进行遍历,检查其中是否包含<>,如果包含说明引用了其他单元格。
- 引用的形式为、等形式,意味着需要将该单元格的内容替换为对应引用单元格的实际内容。
- 使用一个循环替换引用,确保所有引用的单元格内容被正确替换。
- 检测错误:
- 需要考虑到输入数据的合法性,比如引用的单元格是否存在,以及是否引用内容超过100个字符。如果出现错误,输出"-1"。
- 输出结果:
- 所有的单元格内容展开后,按照CSV的格式输出,单元格之间用逗号分隔。
3、时间复杂度
假设每个单元格内容的最大长度为 L,单元格数量为 n,遍历并处理每个单元格的时间复杂度为 O(n * L)。在最坏情况下,所有单元格都有引用关系时,递归的深度最多为 n,因此整体时间复杂度为 O(n^2 * L)。
六、Python算法源码
def replace_cell_references(input_str):
# 分割输入数据,得到单元格内容
cells = input_str.split(",")
# 检查单元格数量是否超过26个
if len(cells) > 26:
return "-1"
# 用一个数组来存储每个单元格的最终值
results = [None] * 26
# 进行单元格引用替换的过程
for i in range(len(cells)):
results[i] = resolve_reference(cells, i)
# 如果有错误(-1),则返回错误结果
if results[i] == "-1":
return "-1"
# 拼接结果为CSV格式输出
return ",".join(filter(None, results[:len(cells)]))
def resolve_reference(cells, index):
cell_content = cells[index]
# 查找引用的标识
start = cell_content.find("<")
end = cell_content.find(">")
# 如果找到<>符号,进行引用替换
if start != -1 and end != -1 and end > start + 1:
# 获取被引用的单元格编号 (A-Z -> 0-25)
referenced_cell = cell_content[start + 1]
if referenced_cell < 'A' or referenced_cell > 'Z':
return "-1" # 引用不合法
ref_index = ord(referenced_cell) - ord('A') # 转换为索引
if ref_index >= len(cells):
return "-1" # 引用单元格不存在
# 获取引用的单元格的实际内容
referenced_content = resolve_reference(cells, ref_index)
if referenced_content == "-1":
return "-1" # 如果引用内容有问题
# 将引用内容替换到当前单元格
cell_content = cell_content[:start] + referenced_content + cell_content[end + 1:]
# 检查单元格内容是否超过100字符
if len(cell_content) > 100:
return "-1" # 内容过长
return cell_content
def main():
# 从控制台读取输入
input_str = input("请输入CSV内容:") # 从控制台读取输入
# 调用方法进行单元格引用替换
result = replace_cell_references(input_str)
# 输出结果
print(result)
if __name__ == "__main__":
main()
七、JavaScript算法源码
function replaceCellReferences(input) {
// 分割输入数据,得到单元格内容
let cells = input.split(",");
// 检查单元格数量是否超过26个
if (cells.length > 26) {
return "-1";
}
// 用一个数组来存储每个单元格的最终值
let results = new Array(26).fill(null);
// 进行单元格引用替换的过程
for (let i = 0; i < cells.length; i++) {
results[i] = resolveReference(cells, i);
// 如果有错误(-1),则返回错误结果
if (results[i] === "-1") {
return "-1";
}
}
// 拼接结果为CSV格式输出
return results.filter(result => result !== null).join(",");
}
function resolveReference(cells, index) {
let cellContent = cells[index];
// 查找引用的标识
let start = cellContent.indexOf("<");
let end = cellContent.indexOf(">");
// 如果找到<>符号,进行引用替换
if (start !== -1 && end !== -1 && end > start + 1) {
// 获取被引用的单元格编号 (A-Z -> 0-25)
let referencedCell = cellContent.charAt(start + 1);
if (referencedCell < 'A' || referencedCell > 'Z') {
return "-1"; // 引用不合法
}
let refIndex = referencedCell.charCodeAt(0) - 'A'.charCodeAt(0); // 转换为索引
if (refIndex >= cells.length) {
return "-1"; // 引用单元格不存在
}
// 获取引用的单元格的实际内容
let referencedContent = resolveReference(cells, refIndex);
if (referencedContent === "-1") {
return "-1"; // 如果引用内容有问题
}
// 将引用内容替换到当前单元格
cellContent = cellContent.substring(0, start) + referencedContent + cellContent.substring(end + 1);
}
// 检查单元格内容是否超过100字符
if (cellContent.length > 100) {
return "-1"; // 内容过长
}
return cellContent;
}
// 从用户输入读取CSV内容
function main() {
const input = prompt("请输入CSV内容:"); // 获取用户输入
// 调用方法进行单元格引用替换
const result = replaceCellReferences(input);
// 输出结果
console.log(result);
}
main();
八、C算法源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_CELLS 26
#define MAX_CONTENT 101
// 解析引用内容的函数声明
char* resolveReference(char* cells[], int index, int numCells);
char* replaceCellReferences(char* input) {
// 分割输入数据,得到单元格内容
char* cells[MAX_CELLS];
char* token = strtok(input, ",");
int numCells = 0;
// 将输入拆分为各个单元格
while (token != NULL) {
if (numCells >= MAX_CELLS) {
return "-1"; // 超过26个单元格,返回错误
}
cells[numCells++] = token;
token = strtok(NULL, ",");
}
// 用一个数组来存储每个单元格的最终值
char* results[MAX_CELLS];
// 进行单元格引用替换的过程
for (int i = 0; i < numCells; i++) {
results[i] = resolveReference(cells, i, numCells);
if (strcmp(results[i], "-1") == 0) {
return "-1"; // 如果有错误,返回错误结果
}
}
// 拼接结果为CSV格式
static char result[MAX_CONTENT * MAX_CELLS] = {0};
for (int i = 0; i < numCells; i++) {
strcat(result, results[i]);
if (i < numCells - 1) {
strcat(result, ",");
}
}
return result;
}
// 解析引用内容的函数
char* resolveReference(char* cells[], int index, int numCells) {
static char buffer[MAX_CONTENT];
strcpy(buffer, cells[index]);
// 查找引用的标识
char* start = strchr(buffer, '<');
char* end = strchr(buffer, '>');
// 如果找到<>符号,进行引用替换
if (start != NULL && end != NULL && end > start + 1) {
char referencedCell = *(start + 1);
if (referencedCell < 'A' || referencedCell > 'Z') {
return "-1"; // 引用不合法
}
int refIndex = referencedCell - 'A'; // 转换为索引
if (refIndex >= numCells) {
return "-1"; // 引用单元格不存在
}
// 获取引用的单元格的实际内容
char* referencedContent = resolveReference(cells, refIndex, numCells);
if (strcmp(referencedContent, "-1") == 0) {
return "-1"; // 如果引用内容有问题
}
// 将引用内容替换到当前单元格
strncpy(start, referencedContent, end - start + 1);
strcpy(start + strlen(referencedContent), end + 1);
}
// 检查单元格内容是否超过100字符
if (strlen(buffer) > 100) {
return "-1"; // 内容过长
}
return buffer;
}
int main() {
char input[256];
printf("请输入CSV内容:");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = 0; // 去掉换行符
// 调用方法进行单元格引用替换
char* result = replaceCellReferences(input);
// 输出结果
printf("%s\n", result);
return 0;
}
九、C++算法源码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#define MAX_CELLS 26
#define MAX_CONTENT 101
using namespace std;
// 解析引用内容的函数声明
string resolveReference(vector<string>& cells, int index, int numCells);
string replaceCellReferences(string input) {
// 分割输入数据,得到单元格内容
vector<string> cells;
string token;
stringstream ss(input);
// 使用逗号分割字符串
while (getline(ss, token, ',')) {
cells.push_back(token);
}
// 检查单元格数量是否超过26个
if (cells.size() > MAX_CELLS) {
return "-1";
}
// 用一个数组来存储每个单元格的最终值
vector<string> results(MAX_CELLS);
// 进行单元格引用替换的过程
for (int i = 0; i < cells.size(); i++) {
results[i] = resolveReference(cells, i, cells.size());
// 如果有错误,返回错误结果
if (results[i] == "-1") {
return "-1";
}
}
// 拼接结果为CSV格式
string result;
for (int i = 0; i < cells.size(); i++) {
result += results[i];
if (i < cells.size() - 1) {
result += ",";
}
}
return result;
}
// 解析引用内容的函数
string resolveReference(vector<string>& cells, int index, int numCells) {
string cellContent = cells[index];
// 查找引用的标识
size_t start = cellContent.find("<");
size_t end = cellContent.find(">");
// 如果找到<>符号,进行引用替换
if (start != string::npos && end != string::npos && end > start + 1) {
char referencedCell = cellContent[start + 1];
if (referencedCell < 'A' || referencedCell > 'Z') {
return "-1"; // 引用不合法
}
int refIndex = referencedCell - 'A'; // 转换为索引
if (refIndex >= numCells) {
return "-1"; // 引用单元格不存在
}
// 获取引用的单元格的实际内容
string referencedContent = resolveReference(cells, refIndex, numCells);
if (referencedContent == "-1") {
return "-1"; // 如果引用内容有问题
}
// 将引用内容替换到当前单元格
cellContent.replace(start, end - start + 1, referencedContent);
}
// 检查单元格内容是否超过100字符
if (cellContent.length() > MAX_CONTENT - 1) {
return "-1"; // 内容过长
}
return cellContent;
}
int main() {
string input;
cout << "请输入CSV内容:";
getline(cin, input); // 从控制台读取输入
// 调用方法进行单元格引用替换
string result = replaceCellReferences(input);
// 输出结果
cout << result << endl;
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。