EOJ刷题记录第六弹

unordered_map中count()与[]的区别

unordered_map 的 count(key) 方法的目的是 专门用来检查键 key 是否存在于 map 中。

1. unordered_map 的 [] 运算符的行为

在 C++ 的 unordered_map 中,当你使用 [] 运算符访问一个键(例如 pos[remain])时,会发生以下情况:

  • 如果键 remain 已经存在于 pos 中: pos[remain] 会返回对 已存在的值 的引用(reference)。你可以读取或修改这个已存在的值。
  • 如果键 remain 不存在于 pos 中:
    • pos[remain] 会在 pos 中 插入一个新的键值对
    • 键是 remain。
    • 值是该值类型的 默认值。对于 int 类型,默认值是 0。
    • pos[remain] 最终会返回对这个 新插入的默认值 0 的引用。

if (pos[remain] != 0) 的问题

当你使用 if (pos[remain] != 0) 时,你的意图是检查 “余数 remain 是否已经出现过(即是否在 pos 中有记录)”。 但是,由于 pos[remain] 的行为,这个判断会产生误导:

  • 情况一:remain 已经出现过,并且在 pos 中有记录,假设记录的位置不是 0 (虽然我们的代码中位置 idx 从 0 开始,但这里为了普遍性假设位置值可以是任何非负整数)。 此时 pos[remain] 返回的是之前记录的位置值 (非零值),所以 if (pos[remain] != 0) **条件为真 (true)**,这似乎是正确的,因为余数确实出现过了。
  • 情况二:remain 第一次出现,之前没有在 pos 中记录。 此时 pos[remain] 会 插入新的键 remain,并赋值为默认值 0,然后返回对这个 0 值的引用。 因此, if (pos[remain] != 0) **条件为假 (false)**,这 也是正确的,因为余数是第一次出现。
  • 情况三:remain 第一次出现,但是 pos 中 *已经存在* 键 remain,并且其对应的值 *恰好是 0* (这种情况在你的代码逻辑中其实不应该发生,因为一旦余数出现过,我们就会记录它的位置 idx,idx 是递增的,除非循环节起始位置恰好是 0,但那也是一个有效的位置,不应该被误判)。 这种情况比较微妙,但在你的代码逻辑中,如果循环节的起始位置恰好是索引 0, 并且你之前错误地使用了 if(pos[remain] != 0), 可能会导致逻辑错误,虽然在这个特定问题中不太容易直接体现出来,但这是一个潜在的隐患。

更严重的问题 (隐藏的副作用):

即使在某些情况下 if (pos[remain] != 0) 看起来好像能工作,但 最根本的问题是 pos[remain] 会在你 *检查* 的同时 *修改* pos 本身 (如果键不存在时会插入默认值)。 这是一种 副作用,使得你的代码逻辑变得不清晰和难以维护。你本意只是想 判断是否存在,结果却意外地 修改了数据结构

Problem #2896 - ECNU Online Judge

读取一行字符串(包括空格)应该怎么处理

  • getchar()是读取一个字符,getline()读取的已经包含’\n’
  • getline(cin, str) 读取一行
  • istringstream 一个变量(str); 构造istringstream
  • while(一个变量 >> string); istringstream类用空格划分读入到string

Problem #1018 - ECNU Online Judge

string 常用技巧

截断子串

1
2
string tmp = tar;
tmp.replace(tar.find(it), it.size(), "");

CodeBlocks设置代码补全

setting->editor->Code completion

  • Keyword sets to additionally include1~9全部勾中
  • 延迟200ms

Comments