华为OD统一考试 - 数据单元的变化替换
题目描述
将一个 csv 格式的数据文件中包含有单元格引用的内容替换为对应单元格内容的实际值。
comma separated values(CSV) 逗号分隔值,csv 格式的数据文件使用逗号 "," 作为分隔符将各单元的内容进行分隔。
输入描述
- 输入只有一行数据,用逗号分隔每个单元格,行尾没有逗号。最多26个单元格,对应编号A~Z。
- 每个单元格的内容包含字母和数字,以及使用 '<>' 分隔的单元格引用,例如:<A>表示引用第一个单元的值。
- 每个单元格的内容,在替换前和替换后均不超过100个字符。
- 引用单元格的位置不受限制,允许排在后面的单元格被排在前面的单元格引用。
- 不存在循环引用的情况,比如下面这种场景是不存在的:A单元恪:aCd<B>8UB单元格:KAy<A>uZq0
- 不存在多重 '<>' 的情况,一个单元只能引用一个其他单元格。比如下面这种场景是不存在的:A单元格:aCdOuB单元格:kAydzcoC单元格:y<<A><B>>d
输出描述
输出替换后的结果
用例
输入 | 1,2<A>00 |
输出 | 1,2100 |
说明 | 第二个单元中有对A单元的引用,A单元格的值为1,替换时,将A单元的内容替代<A>的位置,并和其他内容合并。 |
输入 | 1<B>2,1 |
输出 | 112,1 |
说明 | 第一个单元中有对B单元的引用,B单元格的值为1,耆换时,将第二个数据第单元的内容替代<B>的位置,并和其他内容合并 |
输入 | <A> |
输出 | -1 |
说明 | 第一个单元中有错误的单元格引用方式,输出字符串"-1"表示错误 |
题目解析
本题应该主要是考察递归。
因为单元格内含有"引用1",我们需要根据"引用1",去找引用的单元格1内容,而被引用的单元格1中也可能存在"引用2",我们需要根据"引用2",去找引用的单元格2内容,....,因此需要不停地根据"引用"找下去,直到某个引用的单元格内容中不存在"引用",然后开始回溯。
这个逻辑很容易想到用递归去完成。而且本题已经说明了:
- 不存在循环引用的情况
- 不存在多重 '<>' 的情况(嵌套引用)
因此,递归的逻辑非常简单。
本题用例3给出了一个异常情况:
- <A>
即发生了自引用,我理解其实也算是循环引用。对于异常情况,要输出-1。
本题的主要难点应该在于异常情况的发掘。我觉得,还可能会存在如下异常用例:
- A,B,12<AB>3,D,E,F
- A,B,12<1>3,D,E,F
- A,B,12<Z>3,D,E,F
即
- <>中可能有多个字母(也可能是多个字母,数字)
- <>中的字符不是字母
- <>中的单个字母超出给出的单元格长度范围
这些都算是异常情况。
即我们应该对<>中的内容做如下判断:
- 内容长度只能是1
- 内容只能是A~Z字母
- 内容的单个字母对应的索引,不能超出输入单元格数量
import Foundation func ODTest_2_8() { print("输入只有一行数据,用逗号分隔每个单元格,行尾没有逗号。最多26个单元格,对应编号A~Z") var CSV = (readLine() ?? "").split(separator: ",").map { String($0) } print("输出描述") print("输出替换后的结果") for i in 0 ..< CSV.count { let regExp = /<.*?>/ while let match = CSV[i].firstMatch(of: regExp) { let matchC = CSV[i][match.range] if matchC.count != 3 { print("-1") return } let char = matchC.replacingOccurrences(of: "<", with: "").replacingOccurrences(of: ">", with: "") let ACode = Int(Character("A").asciiValue ?? 0) let matchCode = Int(Character(char).asciiValue ?? 0) let repalceIndex = matchCode - ACode if Character(char) >= Character("A") && Character(char) <= Character("Z") && (ACode + i) != matchCode { CSV[i] = CSV[i].replacingOccurrences(of: matchC, with: CSV[repalceIndex]) } else if (ACode + i) == matchCode { print("-1") return } } } print(CSV.joined(separator: ",")) }