【华为OD-E卷 - 九宫格按键输入 100分(python、java、c++、js、c)】
【华为OD-E卷 - 九宫格按键输入 100分(python、java、c++、js、c)】
题目
九宫格按键输入,有英文和数字两个模式,默认是数字模式,数字模式直接输出数字,英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入 “/” 或者其他字符,则循环中断,输出此时停留的字母。
数字和字母的对应关系如下,注意 0 只对应空格
输入描述
- 输入范围为数字 0~9 和字符’#’、’/’,输出屏幕显示,例如:
在数字模式下,输入 1234,显示 1234 在英文模式下,输入 1234,显示,adg
输出描述
- 输出屏幕显示的字符
用例
用例一:
输入:
2222/22
输出:
222222
用例二:
输入:
#2222/22
输出:
ab
用例三:
输入:
#222233
输出:
ae
python解法
- 解题思路:
- 这段代码的目标是模拟手机键盘的输入处理,特别是传统的T9输入法。具体来说,用户输入一串字符,程序根据输入的字符来模拟手机键盘的按键输入,最终输出对应的文本。
T9输入法:T9输入法使用数字键来输入字母。例如,按键 2 映射到字母 “abc”,按键 3 映射到字母 “def”,依此类推。如果连续按多次同一个数字键,则输出字母的不同选择。例如,按键 “2” 第一次按下输出 “a”,第二次输出 “b”,第三次输出 “c”。
输入规则:
输入是一个字符串,字符可以是字母、空格、数字、特殊字符(如 “#”, “/”, 等)。
特殊字符 # 切换输入模式:如果当前输入是英文模式,则切换为数字输入模式,反之亦然。
切换模式时,缓存区的字符会被清空,并根据输入模式来处理后续字符。
/ 则是用于清空当前缓存区的字符,不做任何字符转换。
字符 char 根据当前模式和按键次数,决定最终字符的输出
class PhoneInput:
# 模拟手机键盘上每个按键对应的字母
KEYS = (" ", ",.", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")
def __init__(self):
# 初始化缓冲区、语言模式、重复计数器
self.buf = [] # 用来缓存输入的字符
self.is_eng = False # 是否处于英文模式
self.rep = 0 # 记录同一按键连续按下的次数
def process(self, text):
"""
处理输入的字符。遍历每个字符,处理后返回最终的文本结果。
"""
for char in text + ' ':
# 如果遇到 "#",切换语言模式并清空当前输入
if char == '#':
self._flush() # 清空当前缓存的字符
self.is_eng = not self.is_eng # 切换英文与数字模式
# 如果遇到 "/",清空当前缓存区
elif char == '/':
self._flush() # 清空当前缓存
else:
self._handle_char(char) # 处理当前字符
return ''.join(self.buf) # 返回最终的字符结果,缓存区内容合并成字符串
def _handle_char(self, char):
"""
根据当前模式(英文或数字)处理当前输入的字符。
"""
# 如果是数字模式,直接将字符加入缓冲区
if not self.is_eng:
self.buf.append(char)
# 如果是英文模式且当前字符与缓存区的最后一个字符不同
elif self.rep == 0 or char != self.buf[-1]:
self._flush() # 清空缓存,准备新输入
self.buf.append(char) # 将当前字符加入缓存
self.rep = 1 # 重置重复计数器
else:
# 如果当前字符与最后一个字符相同,重复计数器加1
self.rep += 1
def _flush(self):
"""
刷新缓存区,根据输入模式决定当前按键的输出字符。
"""
if self.is_eng and self.rep > 0:
# 如果是英文模式,并且有重复按键的记录
key = int(self.buf.pop()) # 获取按键的数字(最后一个字符)
# 根据重复的次数决定字符的选择,使用取余操作循环选择字母
char = self.KEYS[key][(self.rep - 1) % len(self.KEYS[key])]
self.buf.append(char) # 将最终选择的字母加入缓存区
self.rep = 0 # 重置重复计数器
def main():
processor = PhoneInput() # 创建处理器对象
result = processor.process(input()) # 获取输入并处理
print(result) # 输出处理后的结果
if __name__ == "__main__":
main() # 调用main函数,启动程序
java解法
- 解题思路
- 本题的目标是模拟手机键盘的输入处理,类似于传统的T9输入法。每个数字键对应多个字符,连续按同一个数字键时会依次选择对应的字符。用户输入的字符经过处理后,程序返回最终的文本。
输入模式切换:如果遇到 # 字符,输入模式会在“英文模式”和“数字模式”之间切换。
缓存与重复按键处理:如果当前是英文模式且用户连续按下同一个数字键,程序会根据按键的次数输出对应的字符;如果是数字模式,按键直接转换为数字。
处理流程:
输入字符串:逐字符处理输入的字符串。
输入模式切换:
如果是 #,切换输入模式,并清空缓存。
如果是 /,清空当前缓存。
字符处理:根据当前模式处理字符:
如果是“数字模式”,直接将字符追加到输出中。
如果是“英文模式”,则根据字符的重复按下次数,决定输出字符(比如按 2 一次是 “a”,按两次是 “b”)。
清空操作:flush() 方法在需要时将缓存的字符转换为最终的输出字符。
import java.util.Scanner;
public class Main {
// 手机键盘的每个数字键对应的字母映射
private static final String[] KEYS = {" ", ",.", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
private StringBuilder buf; // 用来存储当前的字符序列
private boolean isEng; // 是否处于英文模式
private int rep; // 记录当前字符的重复按下次数
// 构造方法,初始化变量
public Main() {
this.buf = new StringBuilder(); // 初始化缓存区
this.isEng = false; // 默认处于数字模式
this.rep = 0; // 重复计数初始化为0
}
// 处理输入文本的核心方法
public String process(String text) {
// 将输入的文本加上一个空格处理末尾
for (char ch : (text + " ").toCharArray()) {
if (ch == '#') {
flush(); // 如果遇到#,切换模式并清空缓存
isEng = !isEng; // 切换英文模式与数字模式
} else if (ch == '/') {
flush(); // 如果遇到/,清空缓存
} else {
handleChar(ch); // 处理其他字符
}
}
return buf.toString(); // 返回处理后的结果
}
// 处理输入字符的逻辑
private void handleChar(char ch) {
// 如果是数字模式,直接将字符加入缓存
if (!isEng) {
buf.append(ch);
} else if (rep == 0 || ch != buf.charAt(buf.length() - 1)) {
// 如果是英文模式且当前字符与缓存的最后一个字符不同,则清空缓存,重新开始
flush();
buf.append(ch); // 将当前字符添加到缓存
rep = 1; // 重置重复计数为1
} else {
// 如果当前字符与最后一个字符相同,增加重复计数
rep++;
}
}
// 刷新缓存的方法,根据当前输入决定最终字符
private void flush() {
// 只有在英文模式下且有重复计数时,才进行处理
if (isEng && rep > 0) {
// 获取当前字符对应的数字键
int key = Character.getNumericValue(buf.charAt(buf.length() - 1));
// 根据重复次数选取对应的字符
char newChar = KEYS[key].charAt((rep - 1) % KEYS[key].length());
// 替换缓存中的字符
buf.setCharAt(buf.length() - 1, newChar);
}
rep = 0; // 重置重复计数
}
// 主函数,程序入口
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // 创建Scanner对象读取输入
String input = scanner.nextLine(); // 读取用户输入的字符串
scanner.close(); // 关闭Scanner
Main processor = new Main(); // 创建Main对象,处理输入
String result = processor.process(input); // 处理输入
System.out.println(result); // 输出最终结果
}
}
C++解法
- 解题思路
更新中
C解法
更新中
JS解法
-
解题思路
-
这段代码的目标是模拟一个手机键盘的输入处理,类似于传统的T9输入法,其中用户输入的数字键对应多个字母,连续按同一数字键可以依次选择不同的字母。当遇到特殊字符时(例如 # 和 /),程序会根据这些输入切换输入模式或清空当前输入。
输入模式切换:通过 # 来切换输入模式,英文模式和数字模式之间进行切换。英文模式下,连续按同一个数字键可以输出不同的字母;数字模式下,直接输出数字字符。
重复按键处理:在英文模式下,如果连续按下同一个数字键,程序会根据按下的次数来输出不同的字符。例如,按下数字 2 第一次输出 “a”,第二次输出 “b”,第三次输出 “c” 等。
清空操作:通过 / 来清空当前缓存的输入,并结束当前的重复按键计数。
// 引入 readline 模块,用于控制台输入输出
const readline = require("readline");
// 创建 readline 接口,允许从标准输入读取数据
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 定义状态变量
let isEng = false; // 是否处于英文模式,默认为 false,即数字模式
let repeatCount = 0; // 记录同一键的重复按次数
const stack = []; // 用于存储当前输入的字符序列
// 每当读取到一行输入时,触发此事件
rl.on("line", (line) => {
console.log(getResult(line)); // 处理输入并打印结果
// 全局变量重置
isEng = false; // 重置为数字模式
repeatCount = 0; // 重置重复计数
stack.length = 0; // 清空栈
});
// 主处理函数,处理一行输入并返回最终结果
function getResult(s) {
s += " "; // 在输入末尾加上空格,用于处理最后一个字符
// 遍历输入的每个字符
for (let c of s) {
switch (c) {
case "#":
toggleMode(); // 遇到#,切换输入模式
break;
case "/":
interrupt(); // 遇到/,清空当前输入
break;
default:
handleCharacter(c); // 处理普通字符
break;
}
}
// 返回处理后的结果,去掉最后一个空格
return stack.slice(0, stack.length - 1).join("");
}
// 切换输入模式的函数
function toggleMode() {
interrupt(); // 切换模式前,先清空缓存
isEng = !isEng; // 切换英文模式与数字模式
}
// 中断当前输入,清空缓存
function interrupt() {
if (!isEng || stack.length === 0 || repeatCount === 0) return; // 如果不是英文模式,或者没有需要处理的字符,直接返回
stack.push(mapChar(stack.pop(), repeatCount)); // 根据重复次数,更新当前字符
repeatCount = 0; // 重置重复计数
}
// 处理普通字符
function handleCharacter(c) {
if (!isEng) {
// 如果是数字模式,直接将字符添加到栈中
stack.push(c);
} else {
// 如果是英文模式,处理字符
if (repeatCount === 0) {
stack.push(c); // 如果是第一次按下该键,直接加入栈
repeatCount++; // 重复计数加1
} else {
// 如果当前字符与栈顶字符不同,则刷新当前输入
if (c !== stack[stack.length - 1]) {
interrupt(); // 清空当前缓存
stack.push(c); // 加入新的字符
}
repeatCount++; // 重复计数加1
}
}
}
// 定义数字键到字符的映射
const dict = [
" ", // 0 -> 空格
",.", // 1 -> ",."
"abc", // 2 -> "abc"
"def", // 3 -> "def"
"ghi", // 4 -> "ghi"
"jkl", // 5 -> "jkl"
"mno", // 6 -> "mno"
"pqrs", // 7 -> "pqrs"
"tuv", // 8 -> "tuv"
"wxyz", // 9 -> "wxyz"
];
// 根据当前字符和重复次数,返回对应的字母
function mapChar(c, repeat) {
const num = parseInt(c); // 获取数字键
const chars = dict[num]; // 获取该数字键对应的字符映射
return chars[(repeat - 1) % chars.length]; // 根据重复次数选择字符
}
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏