华为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机试#