小蓝的图书馆

问题描述

小蓝是一个热爱阅读的年轻人,他有一个小型图书馆。为了能够管理他的书籍库存,他需要一个程序来记录图书的信息并执行两种操作:添加图书 add 和查找作者 find。

初始小蓝没有书,给出 n 个操作。add 操作给出两个字符串 bookname,author,表示添加的图书图书名和作者;find 操作给出一个字符串 author,你需要输出小蓝的图书馆里这个 author 有多少本图书。

输入格式

第一行一个整数 n,表示有 n 个操作。

之后 n 行,给出操作及后面的参数,如题所述。

给出的字符串长度 len 不超过 10。

输出格式

对每一个 find 操作,你需要输出这个作者在小蓝的图书馆有多少本书,注意是书的数量,不是不同书的数量,同时不同作者可能出现同名的书。


样例输入

7
find author1
add book1 author1
find author1
add book1 author1
find author1
add book1 author2
find author2

样例输出

0
1
2
1

评测数据规模

1≤n≤1000,1≤len≤10。


运行限制

语言 最大运行时间 最大运行内存
C++ 1s 256M
C 1s 256M
Java 2s 256M
Python3 3s 256M

解题思路

为了管理小蓝的图书馆,我们需要记录每本书的信息,并能够根据作者查找其对应的书籍数量。由于同一个作者可能有多本同名的书,我们需要记录每本书的具体信息,而不是仅仅记录不同书的数量。
我们可以使用一个 std::map 或 std::unordered_map 来记录每个作者的书籍数量。具体来说,我们可以将作者作为键,书籍数量作为值。每次执行 add 操作时,我们根据作者增加对应的书籍数量;每次执行 find 操作时,我们根据作者查找并输出对应的书籍数量。


应用方法

1.数据结构选择:使用 std::unordered_map 来存储作者和书籍数量的映射关系,因为 std::unordered_map 的查找和插入操作的平均时间复杂度为 O(1),适合频繁的查找和更新操作。
​2.操作处理:
  ①对于 add 操作,我们将作者作为键,书籍数量作为值,并增加对应的书籍数量。
  ②对于 find 操作,我们根据作者查找并输出对应的书籍数量。


代码答案

编译语言:C++(g++17)

#include  //包含所有标准库头文件,方便使用各种数据结构
using namespace std; //使用标准命名空间,避免写std::前缀

int main()
{
  //优化输入输出,关闭同步,加快cin和cout的速度
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

  int n; cin >> n; //读取操作的数量n

  //定义一个哈希表book,键是作者,值是该作者的书籍数量
  unordered_map book;

  for(int i = 0;i < n;++ i) //循环处理每个操作
  {
    //读取当前操作的类型(add或find)
    string operation; cin >> operation;
    
    if(operation == "add") //如果操作是add
    {
      string bookname, author;
      cin >> bookname >> author; //读取书名和作者
      book[author] ++; //将该作者的书籍数量加1
    }
    else if(operation == "find") //如果操作是find
    {
      string author; cin >> author; //读取要查找的作者
      cout << book[author] << '\n'; //输出该作者的书籍数量
    }
  }
  
  return 0; //程序正常结束
}

代码解释

1.​输入处理:首先读取操作的数量 n,然后依次处理每个操作。
​2.add 操作:读取图书名和作者,并增加该作者的书籍数量。如果该作者尚未在 library 中,library[author] 会自动初始化为 0,然后执行 ++ 操作。
​3.find 操作:读取作者,并输出该作者的书籍数量。如果该作者不在 library 中,library[author] 会返回 0。
​4.输出结果:对于每个 find 操作,输出对应的书籍数量。


示例

输入:​

5
add Book1 AuthorA
add Book2 AuthorB
add Book3 AuthorA
find AuthorA
find AuthorB

输出:​

2
1

解释:​

执行了 3 次 add 操作,添加了 3 本书。
执行了 2 次 find 操作,分别查找 AuthorA 和 AuthorB 的书籍数量。
AuthorA 有 2 本书,AuthorB 有 1 本书。


复杂度分析

1.​时间复杂度:
  ①add 操作:每次 add 操作需要将作者作为键插入哈希表或更新哈希表中的值。unordered_map 的插入和更新操作的平均时间复杂度为 ​O(1)。
​  ②find 操作:每次 find 操作需要根据作者查找哈希表中的值。unordered_map 的查找操作的平均时间复杂度为 ​O(1)。
  ③​总体时间复杂度:对于 n 个操作,总时间复杂度为 ​O(n)。
2.​空间复杂度:
  ①哈希表存储:哈希表存储每个作者及其书籍数量。假设不同的作者数量为 m,则空间复杂度为 ​O(m)。
​  ②输入存储:输入操作和参数需要临时存储,空间复杂度为 ​O(n)。
  ③​总体空间复杂度:空间复杂度为 ​O(m + n)。


注意事项

1.​哈希表的初始值:
当使用 book[author]++ 时,如果 author 不在哈希表中,book[author] 会自动初始化为 0。因此,不需要显式初始化。
​2.输入输出优化:
使用 ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 可以显著加快输入输出速度,尤其是在处理大规模数据时。
​3.字符串长度限制:
题目中说明字符串长度不超过 10,因此不需要考虑字符串过长的问题。
​4.unordered_map 的哈希冲突:
虽然 unordered_map 的平均时间复杂度为 O(1),但在极端情况下(如大量哈希冲突),时间复杂度可能退化为 O(n)。不过,在本题中,字符串长度较短且数量有限,哈希冲突的概率较低。
​5.区分同名书:
题目要求统计的是书籍数量,而不是不同书的数量。因此,即使同一作者有多本同名书,也需要分别计数。


总结

1.​高效性:
使用 unordered_map 实现作者与书籍数量的映射,保证了 add 和 find 操作的高效性,平均时间复杂度为 O(1)。
2.​简洁性:
代码逻辑清晰,通过简单的条件判断和哈希表操作即可完成任务。
3.​适用性:
该代码适用于管理小型图书馆的书籍库存,能够高效地添加书籍和查找作者的书籍数量。
​4.扩展性:
如果需要支持更多操作(如删除书籍或查找书名),可以在此基础上扩展代码逻辑。
​5.优化建议:
如果作者数量非常大(如超过 10^6),可以考虑进一步优化哈希函数或使用其他数据结构(如 map,但时间复杂度会变为 O(log n))。

你可能感兴趣的:(算法,蓝桥杯,c++,哈希表,unordered_map)