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

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

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

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

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

Ответы [ 4 ]

15 голосов
/ 01 ноября 2009

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

Edit: Если вам нужно делать это повторно, ваш подход будет зависеть от данных. Если целые числа в этом массиве колеблются только до 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);
    }
}
1 голос
/ 02 ноября 2009

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

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

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

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

1 голос
/ 02 ноября 2009

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

1 -> 1-й ряд 2 -> 2-й ряд ... n -> n-й ряд

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

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

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

0 голосов
/ 02 ноября 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...