Самый быстрый способ определить, содержит ли 2D-массив элемент?

2

Предположим, что у меня есть 2d-массив:

int[,] my_array = new int[100, 100];

Массив заполняется с помощью int. Каким будет самый быстрый способ проверить, содержится ли элемент целевого значения в массиве?

(* это не домашнее задание, я пытаюсь найти наиболее эффективное решение для этого случая)

  • 0
    Значения массива никак не сортируются.
Теги:
algorithm

4 ответа

15
Лучший ответ

Если массив не отсортирован каким-то образом, я не вижу, как что-то будет быстрее, чем проверка каждого значения с помощью двух операторов. Если он отсортирован, вы можете использовать двоичный поиск.

Изменить: Если вам нужно сделать это несколько раз, ваш подход будет зависеть от данных. Если целые числа в пределах этого массива вмещают только до 256, вы можете иметь логический массив этой длины и проходить через значения в ваших данных, переворачивая биты внутри булевого массива. Если целые числа могут быть выше, вы можете использовать HashSet. Первый вызов вашей функции будет немного медленным, потому что он должен будет индексировать данные. Но последующими вызовами были бы O (1).

Edit1:

Это будет индексировать данные в первом прогоне, при этом сравнительный анализ обнаружил, что Contains занимает 0 миллисекунд для запуска после первого запуска, 13 для индексации. Если бы у меня было больше времени, я мог бы использовать многопоточность и вернуть результат, асинхронно продолжать индексирование при первом вызове. Кроме того, поскольку массивы являются ссылочными типами, изменение значения данных, переданных до или после его индексации, обеспечит странную функциональность, так что это всего лишь образец и должен быть реорганизован до использования.

private class DataContainer
{
    private readonly int[,] _data;
    private HashSet<int> _index;

    public DataContainer(int[,] data)
    {
        _data = data;
    }

    public bool Contains(int value)
    {

        if (_index == null)
        {
            _index = new HashSet<int>();
            for (int i = 0; i < _data.GetLength(0); i++)
            {
                for (int j = 0; j < _data.GetLength(1); j++)
                {
                    _index.Add(_data[i, j]);
                }
            }
        }
        return _index.Contains(value);
    }
}
  • 2
    Предполагая, что массив не отсортирован, распараллеливание поиска может сделать его быстрее, но оно все равно O (n).
  • 1
    @Winston: С таким небольшим массивом, чтобы убедиться, что потоки попадают на разные процессоры ... Я не уверен, что издержки стоили бы того.
1

Предположения:

  • В массивах нет порядка, в которых мы можем использовать
  • Вы собираетесь проверять наличие в массиве несколько раз

Я думаю, что какой-то индекс может работать хорошо. Если вам нужен ответ "да/нет", если данный номер находится в массиве. Для этого можно использовать хеш-таблицу, которая дает вам постоянную O (k) для поиска.

Также не забывайте, что реалистично, для небольших размеров массива MxN, на самом деле может быть быстрее просто выполнить линейный поиск O (n).

1

создать хэш из массива 2d, где

1 → 1-я строка 2 → 2-я строка ... n → nth row

O (n), чтобы проверить наличие данного элемента, если каждая хэш-проверка дает O (1).

Эта структура данных дает вам возможность сохранить ваш 2d-массив.

upd: игнорировать выше, это не дает никакого значения. См. Комментарии

  • 0
    уточни пожалуйста?
  • 0
    int [,] my_array = new int [100, 100]; // my_array -> my_array_int_map map <int, vector <int >> my_array_int_map; for (int i = 0; i <100; i ++) для (int j = 0; j <100; j ++) my_array_int_map [i] .push_back (my_array [i] [j]); Теперь ваш 2d массив скопирован в std: map, который эмулирует хеш-таблицу. Каждый ключ - это номер строки массива 2d, значение - вектор элементов в этой строке.
Показать ещё 10 комментариев
0

Вы можете инкапсулировать сами данные и сохранить словарь вместе с ним, который изменяется после изменения данных.

Ключ Словаря будет значением целевого элемента, а значением будет количество записей элемента. Чтобы проверить, существует ли элемент, просто проверьте словарь для count > 0, который находится где-то между O (1) и O (n). Вы также можете получить другую статистику по данным намного быстрее с этой конструкцией, особенно если данные разрежены.

Самый большой недостаток этого решения заключается в том, что модификации данных имеют больше операций (хотя должно быть O (1), хотя), поэтому, если вы в основном выполняете манипуляции с данными, это может оказаться неприемлемым.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню