#P3237. 九宫格按键输入(200分)
-
1000ms
Tried: 68
Accepted: 23
Difficulty: 5
所属公司 :
华为od
九宫格按键输入(200分)
题目描述
九宫格按键输入系统具有数字模式和英文模式两种输入方式,默认情况下为数字模式。在数字模式下,用户输入的数字会直接显示在屏幕上;在英文模式下,用户连续按同一个数字键会依次选择该键对应的字母。如果在英文模式下输入“/”或其他字符,则循环选择会被中断,当前停留的字母会被输出。
思路
对于题面描述的九宫格可以开个哈希表存,例如cpp

用两个变量一个记录当前是数字模式还是英文模式, 一个记录是否终止了当前循环,也就是记录/,剩下的按照题目意思模拟即可,具体看代码。
具体步骤
-
状态维护:维护当前的输入模式(数字模式或英文模式),初始为数字模式。通过检测
#字符来切换模式。 -
按键处理:
- 数字模式:直接输出数字字符,
/无效,即忽略。 - 英文模式:
- 记录当前连续按下的相同数字键及其按下次数。
- 当按下不同的键或遇到
/时,根据按下次数计算对应的字母并输出。 - 按下
/会立即输出当前选择的字母,并重置计数。
- 数字模式:直接输出数字字符,
-
字母映射:建立数字键到字母的映射关系,例如
2对应abc,3对应def,以此类推。对于每个数字键,按下次数决定选择哪个字母,通过取模运算实现循环选择。 -
边界处理:处理输入结束后可能存在的未输出的字符选择。
-
优化处理:确保处理超长输入时不会出现溢出或性能问题。
cpp
#include <iostream>
#include <unordered_map>
#include <vector>
#include <string>
using namespace std;
int main(){
string input;
// 读取整行输入,包括可能的空格
getline(cin, input);
// 数字键对应的字母映射
unordered_map<char, string> keyMap = {
{'2', "abc"}, {'3', "def"}, {'4', "ghi"},
{'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"},
{'8', "tuv"}, {'9', "wxyz"}, {'0', " "},
{'1', ",."}
};
string output = "";
bool isEnglish = false;
char prevChar = '\0';
int count = 0;
for(char c : input){
if(c == '#'){
// 切换模式
// 在切换模式前,若在英文模式且有未输出的字符,先输出
if(isEnglish && prevChar != '\0'){
if(prevChar == '0'){
output += ' ';
}
else{
string letters = keyMap[prevChar];
int size = letters.size();
// 使用模运算避免越界
output += letters[(count -1) % size];
}
prevChar = '\0';
count = 0;
}
isEnglish = !isEnglish;
continue;
}
if(isEnglish){
if(c == '/'){
// 输出当前字母选择
if(prevChar != '\0'){
if(prevChar == '0'){
output += ' ';
}
else{
string letters = keyMap[prevChar];
int size = letters.size();
output += letters[(count -1) % size];
}
prevChar = '\0';
count = 0;
}
// '/'在英文模式下表示延迟,即分隔
continue;
}
if(c >= '0' && c <= '9'){
if(c == prevChar){
// 同一个键,增加计数
count++;
}
else{
// 不同的键,先输出之前的字母
if(prevChar != '\0'){
if(prevChar == '0'){
output += ' ';
}
else{
string letters = keyMap[prevChar];
int size = letters.size();
output += letters[(count -1) % size];
}
}
// 重置为当前键
prevChar = c;
count = 1;
}
}
else{
// 其他字符忽略
// 根据题目描述,输入仅包含数字、#、/
}
}
else{
// 数字模式下,只输出数字,忽略非数字字符(如 '/')
if(c >= '0' && c <= '9'){
output += c;
}
// 其他字符(如 '/')在数字模式下无效,忽略
}
}
// 最后处理可能剩余的字母
if(isEnglish && prevChar != '\0'){
if(prevChar == '0'){
output += ' ';
}
else{
string letters = keyMap[prevChar];
int size = letters.size();
output += letters[(count -1) % size];
}
}
cout << output;
return 0;
}
python
# 导入必要的模块
from collections import defaultdict
def main():
# 读取整行输入,包括可能的空格
input_str = input().strip()
# 数字键对应的字母映射
key_map = {
'2': "abc", '3': "def", '4': "ghi",
'5': "jkl", '6': "mno", '7': "pqrs",
'8': "tuv", '9': "wxyz", '0': " ",
'1': ",."
}
output = ""
is_english = False
prev_char = None
count = 0
for c in input_str:
if c == '#':
# 切换模式
# 在切换模式前,若在英文模式且有未输出的字符,先输出
if is_english and prev_char is not None:
if prev_char == '0':
output += ' '
else:
letters = key_map[prev_char]
size = len(letters)
# 使用模运算避免越界
output += letters[(count - 1) % size]
prev_char = None
count = 0
is_english = not is_english
continue
if is_english:
if c == '/':
# 输出当前字母选择
if prev_char is not None:
if prev_char == '0':
output += ' '
else:
letters = key_map[prev_char]
size = len(letters)
output += letters[(count - 1) % size]
prev_char = None
count = 0
# '/'在英文模式下表示延迟,即分隔
continue
if '0' <= c <= '9':
if c == prev_char:
# 同一个键,增加计数
count += 1
else:
# 不同的键,先输出之前的字母
if prev_char is not None:
if prev_char == '0':
output += ' '
else:
letters = key_map[prev_char]
size = len(letters)
output += letters[(count - 1) % size]
# 重置为当前键
prev_char = c
count = 1
else:
# 其他字符忽略
pass # 根据题目描述,输入仅包含数字、#、/
else:
# 数字模式下,只输出数字,忽略非数字字符(如 '/')
if '0' <= c <= '9':
output += c
# 其他字符(如 '/')在数字模式下无效,忽略
# 最后处理可能剩余的字母
if is_english and prev_char is not None:
if prev_char == '0':
output += ' '
else:
letters = key_map[prev_char]
size = len(letters)
output += letters[(count - 1) % size]
print(output)
if __name__ == "__main__":
main()
java
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine(); // 读取整行输入,包括可能的空格
// 数字键对应的字母映射
Map<Character, String> keyMap = new HashMap<>();
keyMap.put('2', "abc");
keyMap.put('3', "def");
keyMap.put('4', "ghi");
keyMap.put('5', "jkl");
keyMap.put('6', "mno");
keyMap.put('7', "pqrs");
keyMap.put('8', "tuv");
keyMap.put('9', "wxyz");
keyMap.put('0', " ");
keyMap.put('1', ",.");
StringBuilder output = new StringBuilder();
boolean isEnglish = false;
char prevChar = '\0';
int count = 0;
for (char c : input.toCharArray()) {
if (c == '#') {
// 切换模式
if (isEnglish && prevChar != '\0') {
if (prevChar == '0') {
output.append(' ');
} else {
String letters = keyMap.get(prevChar);
int size = letters.length();
output.append(letters.charAt((count - 1) % size));
}
prevChar = '\0';
count = 0;
}
isEnglish = !isEnglish;
continue;
}
if (isEnglish) {
if (c == '/') {
// 输出当前字母选择
if (prevChar != '\0') {
if (prevChar == '0') {
output.append(' ');
} else {
String letters = keyMap.get(prevChar);
int size = letters.length();
output.append(letters.charAt((count - 1) % size));
}
prevChar = '\0';
count = 0;
}
// '/'在英文模式下表示延迟,即分隔
continue;
}
if (c >= '0' && c <= '9') {
if (c == prevChar) {
// 同一个键,增加计数
count++;
} else {
// 不同的键,先输出之前的字母
if (prevChar != '\0') {
if (prevChar == '0') {
output.append(' ');
} else {
String letters = keyMap.get(prevChar);
int size = letters.length();
output.append(letters.charAt((count - 1) % size));
}
}
// 重置为当前键
prevChar = c;
count = 1;
}
}
// 其他字符忽略
} else {
// 数字模式下,只输出数字,忽略非数字字符(如 '/')
if (c >= '0' && c <= '9') {
output.append(c);
}
// 其他字符(如 '/')在数字模式下无效,忽略
}
}
// 最后处理可能剩余的字母
if (isEnglish && prevChar != '\0') {
if (prevChar == '0') {
output.append(' ');
} else {
String letters = keyMap.get(prevChar);
int size = letters.length();
output.append(letters.charAt((count - 1) % size));
}
}
System.out.println(output);
scanner.close();
}
}
题目内容
九宫格按键输入,有英文和数字两个模式,默认是数字模式,数字模式直接输出数字,英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入 "/" 或者其他字符,则循环中断,输出此时停留的字母。
数字和字母的对应关系如下,注意 0 只对应空格:

输入一串按键,要求输出屏幕显示
- #用于切换模式,默认是数字模式,执行 # 后切换为英文模式;
- /表示延迟,例如在英文模式下,输入 22/222,显示为 bc,数字模式下 / 没有效果;
- 英文模式下,多次按同一键,例如输入 22222,显示为 b;
输入描述
输入范围为数字 0~9 和字符’#’、’/’,输出屏幕显示,例如:
- 在数字模式下,输入 1234,显示 1234
- 在英文模式下,输入 1234,显示 adg
输出描述
输出屏幕显示的字符
样例1
输入
2222/22
输出
222222
说明
默认数字模式,字符直接显示,数字模式下 / 无序
样例2
输入
#2222/22
输出
ab
说明
#进入英文模式,连续的数字输入会循环选择字母,直至输入 / ,故第一段 2222 输入显示 a ,第二段 22 输入显示 b
样例3
输入
#222233
输出
ae
说明
#进入英文模式,连续的数字输入会循环选择字母,直至输入其他数字,故第一段 2222 输入显示 a ,第二段 33 输入显示 e