We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Containers, Strings, Algorithms step 3 of 5
The lookup that writes
int score = scores[name];
In most languages that line reads. In C++ it reads and, if the key is not there, inserts it with a value-initialised value — a zero, an empty string, an empty vector — and hands you a reference to that.
This is not a wart; operator[] has to return a reference you can assign
through, and it cannot do that for a key that does not exist. But it means
the read-only-looking line above can grow your map, and the growth is
invisible until something iterates it.
The tell is that operator[] does not exist on a const map. If you
have ever had to remove a const to make a lookup compile, that was the
language telling you the lookup was a write.
The catalogue
| Missing key | Inserts | On a const map | |
|---|---|---|---|
m[k] |
inserts {} |
yes | does not compile |
m.at(k) |
throws std::out_of_range |
no | fine |
m.find(k) |
returns end() |
no | fine |
m.contains(k) |
returns false | no | fine (C++20) |
m.count(k) |
returns 0 | no | fine |
One lookup, not two
This is the shape almost everyone writes first:
if (m.count(k) > 0) { // lookup 1
use(m[k]); // lookup 2
m[k] += 1; // lookup 3
}
Three searches of the same tree for one key. The alternative asks once and keeps the answer:
auto it = m.find(k); // the only lookup
if (it != m.end()) {
use(it->second);
it->second += 1;
}
An iterator into a map is a handle on the element. it->first is the key,
it->second is the value, and writing through it->second writes into the
map. Nothing needs to be looked up again.
For the insert side, C++17 added the ones that also ask only once:
m.try_emplace(k, args...); // constructs only if absent
m.insert_or_assign(k, value); // sets it either way, tells you which
map or unordered_map?
std::map |
std::unordered_map |
|
|---|---|---|
| Lookup | O(log n) | O(1) average |
| Order | sorted by key | none, and it changes |
| Needs |
operator< |
a hash and operator== |
Reach for unordered_map unless you need the ordering — but note that
iteration order is genuinely unspecified, so anything that prints or hashes
the contents of one is not reproducible.
Your task
std::vector<int> lookup(std::map<std::string, int>& scores,
const std::vector<std::string>& queries, int bonus);
For each query, in order:
-
if the key is present, record its current score and then add
bonusto it; -
if it is absent, record
-1and leave the map alone.
A score of 0 is a real score. The harness reports the results, the map’s
final size, and its values in key order — so an accidental insertion and a
zero mistaken for a miss are both caught.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.