题解:洛谷 P1765 手机
【题目来源】
【题目描述】
一般的手机的键盘是这样的:

要按出英文字母就必须要按数字键多下。例如要按出 \(x\) 就得按 \(9\) 两下,第一下会出 \(w\),而第二下会把 \(w\) 变成 \(x\)。\(0\) 键按一下会出一个空格。
你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘。
【输入】
一行句子,只包含英文小写字母和空格,且不超过 \(200\) 个字符。
【输出】
一行一个整数,表示按键盘的总次数。
【输入样例】
i have a dream
【输出样例】
23
【核心思想】
-
问题分析:给定一个只包含小写字母和空格的字符串(长度不超过 200),需要计算在九宫格手机键盘上输入该字符串所需的总按键次数。每个字母的按键次数取决于它在键盘上的位置(如
a、b、c在按键 2 上,分别按 1、2、3 次;s和z特殊,需要按 4 次;空格按 1 次)。本质是字符到按键次数的映射问题。 -
算法选择:
- 映射表 + 遍历:预先建立一个数组
m,将每个字符映射到其对应的按键次数。然后遍历字符串,累加每个字符的按键次数。 - 实现方式:代码中使用
int m[300]作为映射表,手动初始化每个字母的按键次数(按九宫格键盘布局)。
- 映射表 + 遍历:预先建立一个数组
-
关键步骤:
- 读入:使用
getline(cin, s)读入可能包含空格的整行。 - 构建映射表:
'a'到'r':按 3 个一组循环映射为 1、2、3(即abc→ 1、2、3;def→ 1、2、3;...;pqr→ 1、2、3)。's'和'z':特殊处理,映射为 4。't'到'y':同样按 3 个一组循环映射为 1、2、3(tuv→ 1、2、3;wxyz中的wxy→ 1、2、3;z已特殊处理)。- 空格:映射为 1。
- 统计:遍历字符串,
ans += m[s[i]]。 - 输出:
ans。
- 读入:使用
-
时间/空间复杂度:
- 时间复杂度:\(O(L)\),\(L\) 是字符串长度。
- 空间复杂度:\(O(1)\),映射表固定大小。
-
映射与键盘布局:
- 九宫格键盘映射:熟悉手机键盘布局是解题前提。按键 2: abc,3: def,4: ghi,5: jkl,6: mno,7: pqrs,8: tuv,9: wxyz。每个字母所需的按键次数即它在该键上的位置(从 1 开始),但
s和z分别在 7 和 9 键的第 4 个位置,所以需要按 4 次。 - 直接模拟 vs 映射表:手动构建映射表是最直接的方法,也可以使用数组预定义所有字母的按键次数,但代码中通过循环初始化减少重复。
- 空格处理:题目明确 0 键按一次输出空格,所以空格对应次数为 1。
- 适用场景:这类“键盘输入模拟”是字符串处理中的常见题型,核心是准确建立字符到操作次数的映射。
- 九宫格键盘映射:熟悉手机键盘布局是解题前提。按键 2: abc,3: def,4: ghi,5: jkl,6: mno,7: pqrs,8: tuv,9: wxyz。每个字母所需的按键次数即它在该键上的位置(从 1 开始),但
【算法标签】
入门 #字符串入门
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
int main()
{
string s; // 定义字符串:存储输入的字符串
int ans = 0; // 定义变量:存储最终按键次数总和
int m[300]; // 定义数组:存储每个字符对应的按键次数
int mark = 1; // 定义变量:辅助赋值变量
getline(cin, s); // 读取整行输入(包含空格)
// 初始化字母a-r的按键次数(循环1-3)
for (int i = 'a'; i <= 'r'; i++)
{
m[i] = mark; // 赋值当前字母的按键次数
mark++; // 辅助变量递增
if (mark == 4) // 每3个字母循环一次
mark = 1;
}
// 特殊处理字母s、z和空格
m['s'] = 4; // 字母s需要按4次
m['z'] = 4; // 字母z需要按4次
m[' '] = 1; // 空格需要按1次
mark = 1; // 重置辅助变量
// 初始化字母t-y的按键次数(循环1-3)
for (int i = 't'; i <= 'y'; i++)
{
m[i] = mark; // 赋值当前字母的按键次数
mark++; // 辅助变量递增
if (mark == 4) // 每3个字母循环一次
mark = 1;
}
// 计算字符串中所有字符的按键次数总和
for (int i = 0; i < s.length(); i++)
{
ans += m[s[i]]; // 累加当前字符的按键次数
}
cout << ans; // 输出总按键次数
return 0; // 程序正常结束
}
【运行结果】
i have a dream
23
浙公网安备 33010602011771号