2012-04-26 2 views
8

Мне задали этот вопрос в интервью сегодня. Я попробовал решение, но хотел бы знать, если есть лучший способ решить эту проблему:Алгоритм списка массивов - Интервью

Вопрос: У меня есть ArrayList сказать 500000 элементов таким образом, что значение каждого элемента ArrayList такое же, как индекс , Например: list.get (0) = 0; list.get (1) = 1 ... и т. д. Но только один элемент не синхронизирован с этим упорядочением [i.e list.get (i)! = I]. Как вы находите этот элемент.

Мой ответ: Итерируйте по списку, используя несколько потоков, каждый поток, обрабатывающий определенное сращивание арраиста каждый раз, сравнивая list.get (i) с i. Когда элемент найден, установите некоторую логическую переменную, чтобы указать другим потокам, что элемент был найден.

Есть ли способ решить эту проблему без повторения списка? Или лучший способ?

+0

Без каких-либо намеков о том, где этот номер может быть в списке, вопрос носит скучный характер. – keyser

+0

Я думаю, вам нужно объяснить, что «только один элемент не синхронизирован» на самом деле означает ... это не имеет смысла. См. Мой ответ ниже. Я думаю, что если вы переместите один элемент, все остальные элементы будут не синхронизированы, нет? – duedl0r

+0

@ dued0r элемент не удаляется.Интервьюер спросил, как определить элемент, значение которого не совпадает с индексом. – sachinrahulsourav

ответ

11

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

С учетом этого лучшим алгоритмом является сканирование списка массивов от начала до конца. Таким образом, вы лучше всего используете доступную пропускную способность памяти.

Мне не совсем понятно, как и почему резьба вошла в картину. Это кажется неуместным. Было ли это частью вопроса?

+0

Вопрос довольно унылый, хотя я согласен с вашим мнением. –

+0

@aix Нет, это был мой ответ интервьюеру. Я думал, что использование сращивания массива и обработка итерации арраиста на самом деле будет лучше, но позже я понял, что O (n) не может быть улучшен даже при использовании нескольких потоков. Фактически потоки будут только вводить больше сложности. – sachinrahulsourav

+0

Хотя вы можете столкнуться с проблемой с обоих концов списка в том же цикле. –

2

Вы не можете сделать лучше, чем O(n).

И, во-вторых, я думаю, что это плохая идея говорить о потоках и многопоточности в этих проблемах. Они не представляют интереса вообще. В итоге у вас есть время выполнения O (независимо от того, где ваша константа удаляется в любом случае).

Возможно, интервьюер имел в виду сортированный массив с элементами от 0 до n-1 с индексом от 0 до n-1. Затем переместите один элемент в другую позицию. Но это означает, что все остальные элементы имеют разные индексы! В этом случае вы можете улучшить поиск с помощью двоичного поиска:

Затем вы можете получить элемент в O(log n). Начните посередине и проверьте, равен ли индекс элементу. Если он равен, делайте то же самое с верхней частью половины, если не используете другую часть.

+0

Согласен. И 500 000 не так уж и много для того, чтобы один и тот же поток проходил в настоящее время – keyser

+0

Ваш алгоритм 'O (log n)', кажется, терпит неудачу в списке «1, 0, 2, 3, 4, 5'. Вместо того, чтобы двигаться, вы имели в виду удаление? Тогда это работает. – btilly

+0

@btilly Я думаю, что он имеет в виду, что если общее правило f (n + 1) = f (n) +1 (кроме этой конкретной цели), то здесь идеальный бинарный поиск. – HelloWorld

0

В дополнение к ответу @ Aix, то как о выполнении 2 проверки в цикле:

for (int i = 0; i < list.size/2; i++) 
{ 
    if (i != list.get(i)) 
    { 
    return i; 
    } 
    else if (list.size - i != list.get(list.size - i) 
    { 
    return list.size - i; 
    } 
} 
+1

Мое мнение состоит в том, что при отсутствии тестов производительности цикл разворота лучше всего оставить в JIT-компиляторе. – NPE

+0

@aix Да, я согласен, чисто с точки зрения удобочитаемости я бы избегал делать что-то подобное. –

0
1. iterate through the list 
2. check for the condition in the elements 
3. when that only element found break out the loop... 

Я не думаю, что тема выходит на арену ...

2

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

Фактически, поскольку java 8, решение, параллельное или нет, простое. Я думаю, что больше всего бы принесли:

OptionalInt foundInt = IntStream.range(0, list.size()) 
    .parallelStream() 
    .filter(i -> i != list.get(i)) 
    .findAny(); 
Смежные вопросы