【哈希表】2024D-石头剪刀布游戏
【哈希表】2024D-石头剪刀布游戏
题目描述与示例
本题练习地址:https://www.algomooc.com/problem/P2831
题目描述
石头剪刀布游戏有 3 种出拳形状:石头、剪刀、布。分别用字母 A , B , C 表示。
游戏规则:
- 出拳形状之间的胜负规则如下:
A > B
;B > C
;C > A
;">"
左边一个字母,表示相对优势形状。右边一个字母,表示相对劣势形状。 - 当本场次中有且仅有一种出拳形状优于其它出拳形状,则该形状的玩家是胜利者。否则认为是平局。
- 当发生平局,没有赢家。有多个胜利者时,同为赢家。
例如 1: 三个玩家出拳分别是A, B, C
,由于出现三方优势循环(即没有任何一方优于其它出拳者),判断为平局。
例如 2: 三个玩家,出拳分别是 A, B
,出拳 A
的获胜。
例如 3: 三个玩家,出拳全部是 A
,判为平局。
输入描述
在一场游戏中,每个玩家的信息为一行。玩家数量不超过 1000
。每个玩家信息有 2
个字段,用空格隔开:
- 玩家 ID:一个仅由英文字母和数字组成的字符串
- 出拳形状:以英文大写字母表示,
A 、B 、C
形状。 例:
abc1 A
xyz B
解释:玩家 abc1
出拳为石头( A
)。玩家 xyz
出拳为剪刀( B
)
输出描述
输出为赢家的玩家 ID 列表(一个或多个),每个 ID 一行,按字符串升序排列。如果没有赢家,输出为"NULL"
字符串。例如:
abc1
示例一
输入
abc1 A
xyz B
输出
abc1
说明
A
比 B
有优势,abc1
胜出
示例二
输入
abc1 A
xyz A
输出
NULL
说明
没有优胜的出拳形状,平局
示例三
输入
abc1 A
def A
alic A
xyz B
输出
abc1
alic
def
说明
A
为优胜方,有三个赢家。
解题思路
本题就是童年的石头剪刀布游戏,不用想得太复杂。
用一个哈希表记录所有出A
、B
、C
的人,其中key
为字符串A
或B
或C
中的一种,value
为出该种形状的任命所构成的列表。若
- 哈希表中只存在
1
种键或者3
种键均存在,则说明出现平局,输出"NULL"
- 哈希表中恰好只存在
2
种键。若- 只存在字符串
A
和B
,则逐行输出键A
对应的列表升序排列的结果 - 只存在字符串
B
和C
,则逐行输出键B
对应的列表升序排列的结果 - 只存在字符串
C
和A
,则逐行输出键C
对应的列表升序排列的结果
- 只存在字符串
代码
Python
# 题目:【哈希表】2024D-石头剪刀布游戏
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:哈希表
# 代码看不懂的地方,请直接在群上提问
from collections import defaultdict
# 构建哈希表,设置默认值为list
dic = defaultdict(list)
# 输入次数未知,使用try-except语句进行处理
while 1:
try:
# 输入姓名name和形状k
name, k = input().split()
# 将出拳为k的姓名name,记录在dic[k]这个列表中
dic[k].append(name)
except:
break
# 只有1种形状,或3种形状均有,平局,输出NULL
if len(dic) != 2:
print("NULL")
else:
# 输出A的情况
if "A" in dic and "B" in dic:
ans = dic["A"]
# 输出B的情况
elif "B" in dic and "C" in dic:
ans = dic["B"]
# 输出C的情况
else:
ans = dic["C"]
# 对ans进行排序后逐行输出
for name in sorted(ans):
print(name)
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Map<String, List<String>> dic = new HashMap<>();
while (true) {
try {
String name = scanner.next();
String k = scanner.next();
if (!dic.containsKey(k)) {
dic.put(k, new ArrayList<>());
}
dic.get(k).add(name);
} catch (Exception e) {
break;
}
}
if (dic.size() != 2) {
System.out.println("NULL");
} else {
List<String> ans = new ArrayList<>();
if (dic.containsKey("A") && dic.containsKey("B")) {
ans = dic.get("A");
} else if (dic.containsKey("B") && dic.containsKey("C")) {
ans = dic.get("B");
} else {
ans = dic.get("C");
}
Collections.sort(ans);
for (String name : ans) {
System.out.println(name);
}
}
}
}
C++
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int main() {
map<string, vector<string>> dic;
string name, k;
while (cin >> name >> k) {
dic[k].push_back(name);
}
if (dic.size() != 2) {
cout << "NULL" << endl;
} else {
vector<string> ans;
if (dic.count("A") && dic.count("B")) {
ans = dic["A"];
} else if (dic.count("B") && dic.count("C")) {
ans = dic["B"];
} else {
ans = dic["C"];
}
sort(ans.begin(), ans.end());
for (string name : ans) {
cout << name << endl;
}
}
return 0;
}
时空复杂度
时间复杂度:O(NlogN)
。排序所需的时间复杂度
空间复杂度:O(N)
。哈希表所需空间。