Multiset with Counts
Problem
A multiset can hold the same item many times. Every line is a command: ADD item, REMOVE item (remove one copy), COUNT item, DISTINCT (how many different items are inside) or TOTAL (how many copies are inside altogether). ADD prints ok. REMOVE prints ok or none when the item is not inside. Other commands print a number.
Constraints
- 1 <= lines <= 5000
- items are words without spaces
Examples
Input
ADD a ADD a COUNT a REMOVE a COUNT a TOTAL
Output
ok ok 2 ok 1 1
Solutions
Counts in a map make every command O(1). Removing the item when its count reaches zero keeps DISTINCT equal to the map size.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One result per command.
* Approach: Map of counts.
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
// Step 1: A map from item to its number of copies. An item with 0 copies is removed from the map, so DISTINCT is the map size.
java.util.Map<String, Integer> counts = new java.util.HashMap<String, Integer>();
long total = 0;
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
String[] part = lines[i].split(" ");
if (part[0].equals("ADD")) {
counts.merge(part[1], 1, Integer::sum);
total++;
output[i] = "ok";
} else if (part[0].equals("REMOVE")) {
Integer have = counts.get(part[1]);
if (have == null) {
output[i] = "none";
} else {
// Step 2: Take one copy. Drop the item when the last copy is gone.
if (have == 1) {
counts.remove(part[1]);
} else {
counts.put(part[1], have - 1);
}
total--;
output[i] = "ok";
}
} else if (part[0].equals("COUNT")) {
output[i] = String.valueOf(counts.getOrDefault(part[1], 0));
} else if (part[0].equals("DISTINCT")) {
output[i] = String.valueOf(counts.size());
} else {
output[i] = String.valueOf(total);
}
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (2)
- Why delete the key at zero copies?
- Which commands change the total?