华为OD机试 九宫格按键输入
题目描述
九宫格按键输入,输出显示内容,有英文和数字两个模式,默认是数字模式,数字模式直接输出数字,
英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入 ‘/’ 或者其他字符,则循环中断。
字符对应关系如图所示。
要求输入一串按键,输出屏幕显示内容。
输入描述
输入范围为数字 0~9 和字符 ‘#’、’/’,输出屏幕显示,例如:
在数字模式下,输入 1234,显示 1234
在英文模式下,输入 1234,显示,adg
输出描述
#用于切换模式,默认是数字模式,执行 # 后切换为英文模式;
/ 表示延迟,例如在英文模式下,输入 22/222,显示为 bc;
英文模式下,多次按同一键,例如输入 22222,显示为 b;
示例 1
输入
123
输出
123
示例 2
输入
#22/23044444411
输出
bad i.
Java源码解析
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JiuGongGe {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
scanner.close();
String result = getDisplayResult(input);
System.out.println(result);
}
private static String getDisplayResult(String input) {
Map<Character, String> characterStringMap = buildMap();
boolean isNumber = true;
StringBuffer stringBuffer = new StringBuffer();
int inputLength = input.length();
for (int i = 0; i < inputLength; i++) {
char ch = input.charAt(i);
// # 切换输入法
if (ch == '#') {
isNumber = !isNumber;
continue;
}
// '/' 不拼接
if (ch == '/') {
continue;
}
// 数字直接拼接
if (isNumber) {
stringBuffer.append(ch);
continue;
}
// 英文输入法拼接 空格
if (ch == '0') {
stringBuffer.append(" ");
continue;
}
// 英文输入法时:统计重复字符数量
int repeatCharNum = getRepeatCharNum(input, inputLength, ch, i);
// 向右移动指针,将重复的字符剔除(连续重复字符最终只输入一个字符)
i = i + repeatCharNum;
// 1 对应 ",.", 2 对应 "abc" 等
String ziMu = characterStringMap.get(ch);
if (repeatCharNum > 0) {
int i1 = repeatCharNum % ziMu.length();
stringBuffer.append(ziMu.charAt(i1));
} else {
// 没有重复字母直接输出
stringBuffer.append(ziMu.charAt(repeatCharNum));
}
}
return stringBuffer.toString();
}
private static int getRepeatCharNum(String input, int inputLength, char ch, int i) {
int repeatCharNum = 0;
for (int j = i + 1; j < inputLength; j++) {
char next = input.charAt(j);
// '/'表示中断连续
if (next == '/') {
break;
}
// 当前字符不等于下一个字符
if (ch != next) {
break;
}
repeatCharNum++;
}
return repeatCharNum;
}
private static Map<Character, String> buildMap() {
Map<Character, String> map = new HashMap<>();
map.put('1', ",.");
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
return map;
}
}
栈结构解法
本题看上去就是一道逻辑题,但是可以利用栈结构来处理。
本题的主要难点在于处理英文模式下的输入。
首先,英文模式下,如果输入的是0-9的数字的话,则是需要转为对应的英文,但是由于我们可以输入多次重复数字,来切换对应于同一个数字的英文,比如英文模式下,输入222,即对应c,输入22,即对应b,输入2,即对应a,输入2222,又对应a。
因此,英文模式下的输入,我们不应该直接将输入的数字转为英文,而是应该缓存输入数字的重复次数,在下一次输入不同的数字或者输入'/'时,则需要将重复的数字输入转为对应英文。
我的解题思路是,遍历输入字符串的每一个字符,并尝试将它们压入stack栈中,而在压栈前,需要先检查stack栈顶元素top是否为一个数组,若为数组,则数组对应一个尚未转化成英文的输入,数组元素含义为:[ 数字,重复次数 ]。
此时,如果输入模式mode是数字模式,或者是英文模式下输入的'/',再或者输入模式mode是英文模式,但是输入的字符(即遍历的字符)和栈顶top数组的top[0]数字不同的话,则此时我们需要将栈顶top数组转为英文。
转化规则为:
比如top = [2, 5],即英文模式下,按了5次2,此时应该输出英文b。
按键2对应的英文 arr = ['a', 'b','c'] ,len = arr.length ,count=5,
因此top = [2, 5] 对应的英文为 arr[(count-1)% len],即 arr[4%3]= arr[1]
当我们将栈顶数组转为英文后,再考虑将遍历的字符压入栈顶,但是需要注意的是,如果遍历的字符是数字,且在数字模式下输入,则直接压入栈顶,若是英文模式下的输入,则需要转为[num,1]数组下入栈顶,即数字num被重复按了1次。
如果栈顶数组的top[0],和英文模式下,输入的数字相同,则top[1]++,表示英文模式下,top[0]数字又被按了一次。
而栈顶元素不是数组时的处理方案,和上面将栈顶数组转为英文后的操作一致。
JavaScript算法源码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
const arr = [...line];
console.log(getResult(arr));
});
function getResult(arr) {
const map = [
" ",
",.",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz",
];
const stack = [];
let mode = true; // true为数字模式,false为英文模式
arr.forEach((char) => {
switch (char) {
case "#":
mode = !mode;
break;
case "/":
if (!mode) ipt(mode, stack, map);
break;
default:
ipt(mode, stack, map, char);
}
});
ipt(mode, stack, map);
return stack.join("");
}
function ipt(mode, stack, map, char) {
const top = stack[stack.length - 1];
if (Array.isArray(top)) {
if (!mode && top[0] == char) {
return top[1]++;
} else {
const [num, count] = stack.pop();
const arr = map[num];
const len = arr.length;
stack.push(arr[(count - 1) % len]);
}
}
if (char) {
if (mode) {
stack.push(char);
} else {
stack.push([char, 1]);
}
}
}
#华为OD机试#
查看3道真题和解析