главная новое лучшее написать
3

Ссылка на задачу ­– 3160. Find the Number of Distinct Colors Among the Balls.

Описание задачи 😊

Идея 💡

Основная идея заключается в использовании двух хеш-таблиц:

Это позволяет за константное (в среднем) время обновлять информацию при каждом запросе и быстро определять число уникальных цветов.

Детали подхода 🔍

  1. Обновление цвета шарика:
    • При выполнении запроса, если шарик уже был раскрашен, получаем его старый цвет и уменьшаем счётчик в color_counts. Если счётчик для старого цвета становится равным нулю, уменьшаем количество уникальных цветов.
  2. Установка нового цвета:
    • Обновляем запись в ball_to_color новым цветом. Затем увеличиваем счётчик для нового цвета в color_counts. Если новый цвет появляется впервые (счётчик становится равным 1), увеличиваем количество уникальных цветов.
  3. Формирование результата:
    • После каждого запроса записываем текущее число уникальных цветов в результирующий вектор.

Асимптотика ⏱️

Исходный код 💻

use std::collections::HashMap;
use std::collections::hash_map::Entry;

impl Solution {
    pub fn query_results(limit: i32, queries: Vec<Vec<i32>>) -> Vec<i32> {
        let mut ball_to_color = HashMap::new();
        let mut color_counts = HashMap::new();
        let mut distinct_colors = 0;
        let mut result = Vec::with_capacity(queries.len());

        for query in queries {
            let (ball, new_color) = (query[0], query[1]);

            // If the ball was already painted, update the count for the old color.
            if let Some(old_color) = ball_to_color.insert(ball, new_color) {
                let Entry::Occupied(count) = color_counts.entry(old_color)
                    .and_modify(|count| *count -= 1) else {
                    unreachable!("color should be accounted")
                };
                if *count.get() == 0 {
                    distinct_colors -= 1;
                }
            }

            // Update the count for the new color.
            if 1 == *color_counts.entry(new_color)
                .and_modify(|count| *count += 1)
                .or_insert(1) 
            {
                distinct_colors += 1;
            }

            result.push(distinct_colors);
        }

        result
    }
}

Tags: #rust #algorithms #hashmap

1 finder 07-02-2025

Я, видимо, туплю, хеш-таблицы-то зачем? Двух массивов хватило бы?

ответить
1 leetcoder 09-02-2025

В ограничениях задачи - шариков может быть до миллиарда: никто не гарантирует, что все бесцветные шарики в памяти уложатся.
В подходе с хэш-таблицей мы только цветные шарики храним в памяти, а их не больше, чем число операций.

ответить
1 finder 09-02-2025

Опять я провалил АА, что ж такое-то.

Если серьезно, то это пример, когда литкод-стайл измеряет не просто не то же самое, что нужно потом на работе, а прямо противоположную вещь. Сама задача очень простая, но, оказывается, можно ошибиться вот так. При этом в работе думать о том, что фраза "Даны шарики с уникальными метками от 0 до limit (всего limit + 1 шариков)" может означать, что их может оказаться миллиард, натурально вредно. Речь не о том, что не нужно оптимизировать заранее (иначе пол-литкода можно было бы стереть), но ограничения на количества объектов и операций обычно читаются из физического смысла происходящего. Запросов или, там, транзакций может быть миллиард, пользователей уже вряд ли, если вы не Мета, а шариков будут десятки, может, сотни. Особенно если они перенумерованные (а не снабженные, скажем, guid-ами).

ответить
1 leetcoder 10-02-2025

Как будто бы, ты слишком строк к себе!

Не понять интервьюера не является грехом. Важно же, просто уметь быстро перестраивать своё решение, если что-то было изначально понято неправильно. И как раз обладание таким скилом, на мой взгляд, является гипер-полезным в рабочем процессе. И отлично, если ты его сумел показать на собеседовании!

ответить