(200分)- 九宫格按键输入(Java & JS & Python)

题目描述

九宫格按键输入,输出显示内容,有英文和数字两个模式,默认是数字模式,数字模式直接输出数字,英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入”/”或者其他字符,则循环中断。

字符对应关系如图:

要求输入一串按键,输出屏幕显示。

输入描述

输入范围为数字 0~9 和字符’#’、’/’,输出屏幕显示,例如,

在数字模式下,输入 1234,显示 1234

在英文模式下,输入 1234,显示,adg

输出描述

#用于切换模式,默认是数字模式,执行#后切换为英文模式;

/表示延迟,例如在英文模式下,输入 22/222,显示为 bc;

英文模式下,多次按同一键,例如输入 22222,显示为 b;

用例
输入 123#222235/56
输出 123adjjm

题目解析

本题考察逻辑分析能力和栈结构的应用。

解题思路如下:

  1. 初始化:

    • 定义栈stack存储结果
    • 设置isEng标志记录当前模式(false为数字模式,true为英文模式),初始为false
  2. 遍历字符串s的每个字符c:

    • 遇到'#':切换模式前需检查:
      • 若当前为英文模式,需先处理栈顶数字的转换
      • 然后切换模式:isEng = !isEng
    • 遇到'/':处理循环中断
      • 仅当英文模式时才需处理栈顶数字转换
    • 其他字符:
      • 数字模式:直接入栈
      • 英文模式:
        • 栈顶字符与c不同:需中断循环(转换栈顶数字)
        • 相同:增加栈顶数字的重复计数
  3. 循环中断逻辑的注意事项:

    • 必须处于英文模式
    • 栈不能为空

Java算法源码
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println(getResult(sc.nextLine()));
  }

  static String[] dict = {" ", ",.", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

  static LinkedList<Character> stack = new LinkedList<>();
  static int topRepeat = 0;
  static boolean isEng = false;

  public static String getResult(String s) {
    s += " ";

    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);

      switch (c) {
        case '#':
          // 如果输入”/”或者其他字符,则循环中断
          interrupt();
          // #用于切换模式
          isEng = !isEng;
          break;
        case '/':
          // 如果输入”/”或者其他字符,则循环中断
          interrupt();
          break;
        default:
          // 数字模式
          // 直接输出数字
          if (!isEng) {
            stack.add(c);
            break;
          }

          // 英文模式,需要检查栈顶
          // 如果栈顶不是英文模式字符(这里可以基于topRepeat判断,topRepeat是英文模式下对应按键的重复次数,如果为0,则说明栈顶存储的不是英文模式字符),则缓存对应字符c,并记录重复次数
          if (topRepeat == 0) {
            stack.add(c);
            topRepeat++;
            break;
          }

          // 如果栈顶字符有重复次数,则此时需要比较当前按键c和之前重复的按键stack.getLast是否相同
          if (c != stack.getLast()) {
            // 如果输入”/”或者其他字符,则循环中断
            interrupt();
            stack.add(c);
          }
          topRepeat++;
      }
    }

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < stack.size() - 1; i++) sb.append(stack.get(i));
    return sb.toString();
  }

  // 英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入”/”或者其他字符,则循环中断
  // interrupt用于处理循环中断后的逻辑
  public static void interrupt() {
    if (!isEng || stack.size() == 0 || topRepeat == 0) return;
    stack.add(map(stack.removeLast(), topRepeat));
    topRepeat = 0;
  }

  // 基于dict,获取一个数字c被重复repeat次后,对应的字符
  public static char map(char c, int repeat) {
    int num = Integer.parseInt(c + "");
    String s = dict[num];
    int i = (repeat - 1) % s.length();
    return s.charAt(i);
  }
}

JS算法源码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const stack = [];
let topRepeat = 0;
let isEng = false;

rl.on("line", (line) => {
  console.log(getResult(line));

  // 如果需要测试多组用例,这里需要将全局变量重置
  stack.length = 0;
  topRepeat = 0;
  isEng = false;
});

function getResult(s) {
  s += " ";

  for (let c of s) {
    switch (c) {
      case "#":
        // 如果输入”/”或者其他字符,则循环中断
        interrupt();
        // #用于切换模式
        isEng = !isEng;
        break;
      case "/":
        // 如果输入”/”或者其他字符,则循环中断
        interrupt();
        break;
      default:
        // 数字模式直接输出数字
        if (!isEng) {
          stack.push(c);
          break;
        }

        // 英文模式,需要检查栈顶
        // 如果栈顶不是英文模式字符(这里可以基于topRepeat判断,topRepeat是英文模式下对应按键的重复次数,如果为0,则说明栈顶存储的不是英文模式字符),则缓存对应字符c,并记录重复次数
        if (topRepeat == 0) {
          stack.push(c);
          topRepeat++;
          break;
        }

        // 如果栈顶字符有重复次数,则此时需要比较当前按键c和之前重复的按键stack.getLast是否相同
        if (c != stack.at(-1)) {
          // 如果输入”/”或者其他字符,则循环中断
          interrupt();
          stack.push(c);
        }
        topRepeat++;
    }
  }

  return stack.slice(0, stack.length - 1).join("");
}

// 英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入”/”或者其他字符,则循环中断
// interrupt用于处理循环中断后的逻辑
function interrupt() {
  if (!isEng || stack.length == 0 || topRepeat == 0) return;
  stack.push(map(stack.pop(), topRepeat));
  topRepeat = 0;
}

const dict = [
  " ",
  ",.",
  "abc",
  "def",
  "ghi",
  "jkl",
  "mno",
  "pqrs",
  "tuv",
  "wxyz",
];

// 基于dict,获取一个数字c被重复repeat次后,对应的字符
function map(c, repeat) {
  const num = parseInt(c);
  const s = dict[num];
  const i = (repeat - 1) % s.length;
  return s[i];
}

Python算法源码
# 输入获取
s = input()

# 全局变量
stack = []
topRepeat = 0
isEng = False

dictionary = (" ", ",.", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")


# 基于dictionary,获取一个数字c被重复repeat次后,对应的字符
def mapping(c, repeat):
    num = int(c)
    s1 = dictionary[num]
    i = (repeat - 1) % len(s1)
    return s1[i]


# 英文模式连续按同一个按键会依次出现这个按键上的字母,如果输入”/”或者其他字符,则循环中断
# interrupt用于处理循环中断后的逻辑
def interrupt():
    global topRepeat
    if not isEng or len(stack) == 0 or topRepeat == 0:
        return
    stack.append(mapping(stack.pop(), topRepeat))
    topRepeat = 0


# 算法入口
def getResult():
    global s
    global isEng
    global topRepeat

    s += " "

    for c in s:
        if c == '#':
            # 如果输入”/”或者其他字符,则循环中断
            interrupt()
            # #用于切换模式
            isEng = not isEng
        elif c == '/':
            # 如果输入”/”或者其他字符,则循环中断
            interrupt()
        else:
            # 数字模式直接输出数字
            if not isEng:
                stack.append(c)
                continue

            # 英文模式,需要检查栈顶
            # 如果栈顶不是英文模式字符(这里可以基于topRepeat判断,topRepeat是英文模式下对应按键的重复次数,如果为0,则说明栈顶存储的不是英文模式字符),则缓存对应字符c,并记录重复次数
            if topRepeat == 0:
                stack.append(c)
                topRepeat += 1
                continue

            # 如果栈顶字符有重复次数,则此时需要比较当前按键c和之前重复的按键stack.getLast是否相同
            if c != stack[-1]:
                # 如果输入”/”或者其他字符,则循环中断
                interrupt()
                stack.append(c)

            topRepeat += 1

    return "".join(stack[:-1])


# 算法调用
print(getResult())
Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐