题目链接:https://www.nowcoder.com/test/11647029/summary
1.时钟:
题目描述:
小W有一个电子时钟用于显示时间,显示的格式为HH:MM:SS,HH,MM,SS分别表示时,分,秒。其中时的范围为[‘00’,‘01’…‘23’],分的范围为[‘00’,‘01’…‘59’],秒的范围为[‘00’,‘01’…‘59’]。
但是有一天小W发现钟表似乎坏了,显示了一个不可能存在的时间“98:23:00”,小W希望改变最少的数字,使得电子时钟显示的时间为一个真实存在的时间,譬如“98:23:00”通过修改第一个’9’为’1’,即可成为一个真实存在的时间“18:23:00”。修改的方法可能有很多,小W想知道,在满足改变最少的数字的前提下,符合条件的字典序最小的时间是多少。其中字典序比较为用“HHMMSS”的6位字符串进行比较。
解题思路分析:
题目的要求非常的明确,就是要我们判断这个钟是否是显示的真实存在的时间,如果不是的话,我们可以通过改变任意一位上的数字,问我们最少需要多少次改动,使得这个时钟上的时间既能表示真实存在的时间,也能使得整个时钟的字典序最小。
好的,首先来分析一下什么情况下时钟显示的时间是不存在的,因为不能显示负数,所以只要小时 >= 24,分、秒 >= 60就是不存在的,注意是>=不是>,小编也因此错交了一次。那再来分析,如果时间是不存在的,那么怎么改是最合理的,因为我们既要时间存在也要字典序最小,不难想到,我们需要做的就是将高位变为0即可,所以我们只需要将错的地方(H,M,S)的高位改为0就可以得到答案。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char str[10];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int H, M, S;
scanf("%d:%d:%d", &H, &M, &S);
if(H >= 24) {
H = H%10;
}
if(M >= 60) {
M = M%10;
}
if(S >= 60) {
S = S%10;
}
printf("%02d:%02d:%02d\n", H, M, S);
}
return 0;
}
2.会话列表
题目描述:
小云正在参与开发一个即时聊天工具,他负责其中的会话列表部分。
会话列表为显示为一个从上到下的多行控件,其中每一行表示一个会话,每一个会话都可以以一个唯一正整数id表示。
当用户在一个会话中发送或接收信息时,如果该会话已经在会话列表中,则会从原来的位置移到列表的最上方;如果没有在会话列表中,则在会话列表最上方插入该会话。
小云在现在要做的工作是测试,他会先把会话列表清空等待接收信息。当接收完大量来自不同会话的信息后,就输出当前的会话列表,以检查其中是否有bug。
解题思路分析:
凡是用过聊天工具(QQ,微信等)的人,应该这道题的题意不难理解,题目的要求是说,给我们带先后顺序的发消息对象,问我们最后的会话列表的消息对象顺序应该是怎么样的。
这题我们其实可以反过来做,因为最后发送消息的一定是在最上面的,同理倒数第二个发送消息的应该是在第二个位置,但是如果出现重复出现的消息对象,那么位置肯定是按靠后也就是消息对象最后一次发送消息的时间为准来决定位置,所以我们需要记录一下消息对象有没有出现过即可得到答案。
代码:
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 200+5;
map<int, int> Map;
int id[maxn], ans[maxn];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n, num = 0;
cin >> n;
Map.clear();
for(int i=0; i<n; i++) {
cin >> id[i];
}
for(int i=n-1; i>=0; i--) {
if(Map[id[i]] == 0) {
ans[num++] = id[i];
Map[id[i]] = 1;
}
}
for(int i=0; i<num; i++) {
if(i == num-1) {
cout << ans[i] << endl;
}
else {
cout << ans[i] << " ";
}
}
}
return 0;
}
3.字符迷阵:
题目描述:
字符迷阵是一种经典的智力游戏。玩家需要在给定的矩形的字符迷阵中寻找特定的单词。
在这题的规则中,单词是如下规定的:
1. 在字符迷阵中选取一个字符作为单词的开头;
2. 选取右方、下方、或右下45度方向作为单词的延伸方向;
3. 以开头的字符,以选定的延伸方向,把连续得到的若干字符拼接在一起,则称为一个单词。
以图1为例,如果要在其中寻找单词"WORD",则绿色框所标示的都是合法的方案,而红色框所标示的都是不合法的方案。
现在的问题是,给出一个字符迷阵,及一个要寻找的单词,问能在字符迷阵中找到多少个该单词的合法方案。注意合法方案是可以重叠的,如图1所示的字符迷阵,其中单词"WORD"的合法方案有4种。
解题思路分析:
题意是说,给我们一个矩形和一个字符串,让我们在这个矩阵中找到出现过多少个给我们的字符串,且要求匹配的方式只能是从左到又、从上到下、从左上到右下的顺序。很明显这题就是一个换了个形式的字符串匹配,本来小编是想用三个方向的KMP来做这道题的,但是仔细一分析,矩阵为100 * 100的,字符串大小为10的,匹配方向为3种,那么直接暴力匹配复杂度也不过就10^5,那么这题应该不是考察我们的KMP算法,而是考察我们在矩阵中的三个方向的字符串匹配的编码能力。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100+5;
int dir[3][2] = {{0,1}, {1,0}, {1,1}};
char Map[maxn][maxn];
char str[10];
int n, m;
bool flag(int x, int y) {
if(x >= n || x < 0 || y >= m || y < 0) {
return false;
}
return true;
}
int main() {
int T;
cin >> T;
while(T--) {
cin >> n >> m;
for(int i=0; i<n; i++) {
cin >> Map[i];
}
cin >> str;
int len = strlen(str), num = 0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(Map[i][j] == str[0]) {
for(int d=0; d<3; d++) {
int tx = i, ty = j, ok = 1;
for(int k=1; k<len; k++) {
tx += dir[d][0];
ty += dir[d][1];
if(!flag(tx, ty) || Map[tx][ty] != str[k]) {
ok = 0;
break;
}
}
if(ok) {
num++;
}
}
}
}
}
cout << num << endl;
}
}