Find the Number of Distinct Colors Among the Balls

medium hash table simulation counting

Problem

There are limit + 1 balls labeled 0..limit, all initially uncolored. Each query [x, y] repaints ball x with color y (overwriting any previous color). After each query, report how many distinct colors are currently in use. Return the array of answers, one per query. Uncolored balls do not count as a color.

Inputlimit = 4, queries = [[1,4],[2,5],[1,3],[3,4]]
Output[1, 2, 2, 3]
After q2 ball 1 is repainted 4→3, so color 4 vanishes while color 3 appears: still 2 distinct colors.

def queryResults(limit, queries):
    ballColor = {}                       # ball -> its current color
    colorCount = {}                      # color -> how many balls wear it
    result = []
    for x, y in queries:
        if x in ballColor:               # ball was colored before
            old = ballColor[x]
            colorCount[old] -= 1         # that color loses one ball
            if colorCount[old] == 0:
                del colorCount[old]      # color no longer present
        ballColor[x] = y                 # repaint ball x with color y
        colorCount[y] = colorCount.get(y, 0) + 1
        result.append(len(colorCount))   # distinct colors right now
    return result
function queryResults(limit, queries) {
  const ballColor = new Map();           // ball -> its current color
  const colorCount = new Map();          // color -> how many balls wear it
  const result = [];
  for (const [x, y] of queries) {
    if (ballColor.has(x)) {              // ball was colored before
      const old = ballColor.get(x);
      colorCount.set(old, colorCount.get(old) - 1);
      if (colorCount.get(old) === 0)     // color no longer present
        colorCount.delete(old);
    }
    ballColor.set(x, y);                 // repaint ball x with color y
    colorCount.set(y, (colorCount.get(y) || 0) + 1);
    result.push(colorCount.size);        // distinct colors right now
  }
  return result;
}
int[] queryResults(int limit, int[][] queries) {
    Map<Integer, Integer> ballColor = new HashMap<>();   // ball -> color
    Map<Integer, Integer> colorCount = new HashMap<>();  // color -> count
    int[] result = new int[queries.length];
    for (int i = 0; i < queries.length; i++) {
        int x = queries[i][0], y = queries[i][1];
        if (ballColor.containsKey(x)) {                  // colored before
            int old = ballColor.get(x);
            colorCount.merge(old, -1, Integer::sum);     // that color -1
            if (colorCount.get(old) == 0)
                colorCount.remove(old);                  // color gone
        }
        ballColor.put(x, y);                             // repaint ball x
        colorCount.merge(y, 1, Integer::sum);
        result[i] = colorCount.size();                   // distinct colors
    }
    return result;
}
vector<int> queryResults(int limit, vector<vector<int>>& queries) {
    unordered_map<int, int> ballColor;          // ball -> its color
    unordered_map<int, int> colorCount;         // color -> count
    vector<int> result;
    for (auto& q : queries) {
        int x = q[0], y = q[1];
        auto it = ballColor.find(x);
        if (it != ballColor.end()) {            // colored before
            int old = it->second;
            if (--colorCount[old] == 0)         // that color loses a ball
                colorCount.erase(old);          // color no longer present
        }
        ballColor[x] = y;                       // repaint ball x
        colorCount[y]++;
        result.push_back(colorCount.size());    // distinct colors now
    }
    return result;
}
Time: O(n) Space: O(n)