Имя: Пароль:
IT
 
Задача на поиск в массиве
0 Ненавижу 1С
 
гуру
07.12.09
09:26
Дан массив целых чисел, в котором все числа встречаются ровно 2 раза, кроме одного, которое входит только 1 раз. Нужно за конечное число проходов O(1) массива и используя дополнительной памяти не более O(1) найти его.
1 Волесвет
 
07.12.09
09:30
хм... ню решение то простое подхватываем элемент и бежим по массиву если есть тоды прерываем берем следующий и снова бежим - если не находим тоды искомое...
что нить поизощреннее на ум не приходит - понедяльник
2 Chum
 
07.12.09
09:31
Выгрузить в ТЗ, добавить числовую колонку, заполнить единичками, свернуть. просуммировав. Найти строку, где значение в колонке = 1
3 Chum
 
07.12.09
09:34
массив можно отсортировать, затем сравнивать рядом стоящие элементы. тогда за один проход
4 Rie
 
07.12.09
09:35
(0) Перексорим весь массив - получим искомое.
5 Fragster
 
гуру
07.12.09
09:36
(3) такой сортировки нету
6 Fragster
 
гуру
07.12.09
09:37
(5) в смысле - в один проход
7 NikVars
 
07.12.09
09:40
(0) "за конечное число проходов"...
А за бесконечное число проходов это как?!
:)))
8 Ненавижу 1С
 
гуру
07.12.09
09:45
(1)(2)(3)(4) не обойтись за О(1)
(7) можешь конечное убрать, если смущает
9 Ненавижу 1С
 
гуру
07.12.09
09:46
(2) и ТЗ требует памяти больше чем О(1)
10 ДенисЧ
 
07.12.09
09:46
Что-то я не порйму, как можно произвольный массив пробежать за константное время...
11 H A D G E H O G s
 
07.12.09
09:47
(8) Что значит O(1)
Скока точно в граммах © Не помню, реклама какая-то...
12 Ненавижу 1С
 
гуру
07.12.09
09:47
(10) не за константное время, а число проходов константа
13 Ненавижу 1С
 
гуру
07.12.09
09:47
(11) не зависит от длины входящего массива в данном случае
14 ДенисЧ
 
07.12.09
09:47
(12) тады (1)...
15 H A D G E H O G s
 
07.12.09
09:50
(14) Неа.
16 ДенисЧ
 
07.12.09
09:51
(15) why?
17 H A D G E H O G s
 
07.12.09
09:52
(16) Количество циклов в (1) зависит от длинны массива
18 Ненавижу 1С
 
гуру
07.12.09
09:52
(14) общее число сдвигов по массиву должно быть O(N), а там итеаций O(N), а сдвигов O(N^2)
19 Ненавижу 1С
 
гуру
07.12.09
09:52
+(18) а там проходов O(N)
20 H A D G E H O G s
 
07.12.09
09:53
(18) Вы выражайтесь русскими словами пожалуйста.
21 Ненавижу 1С
 
гуру
07.12.09
09:53
(20) поправился в (19)
22 Rie
 
07.12.09
09:53
(4) Как это? Находится за 1 (Один) проход - благодаря свойству x XOR x = 0.
23 Rie
 
07.12.09
09:53
(22)->(8)
24 Ненавижу 1С
 
гуру
07.12.09
09:54
(22) чего?
25 H A D G E H O G s
 
07.12.09
09:54
(22) Что с чем ксорить будем?
26 H A D G E H O G s
 
07.12.09
09:54
Массив надо отсортировать сначало
27 H A D G E H O G s
 
07.12.09
09:55
Потом сравнивать i элемент с i+1 элементом в i/2-1 цикле
28 ДенисЧ
 
07.12.09
09:55
(26) Сортировка уже выходит за ограничения...
29 Rie
 
07.12.09
09:58
(25) Всё со всем.

R = 0;
for (int i=0; i<N; i++)
  R ^= A[i];
30 Rie
 
07.12.09
10:00
+(29) XOR - ассоциативен и коммутативен, x^x=0.
Числа встречаются по 2 раза, кроме одного.
31 Ненавижу 1С
 
гуру
07.12.09
10:01
(29) красавчик
32 H A D G E H O G s
 
07.12.09
10:02
(30) Тоесть:

((12 xor 25) xor (12)) xor(25) =0 ?
33 Rie
 
07.12.09
10:03
(32) Не поверишь - но так и есть.
34 Ненавижу 1С
 
гуру
07.12.09
10:08
Теперь 2-я часть: таких числа (встречающихся один раз) - два
35 МихаилМ
 
07.12.09
11:50
то (34)
если осортировать то хоть Все не повторяющиеся.
36 Ненавижу 1С
 
гуру
07.12.09
11:51
(35) отсортировать очевидно нельзя
37 МихаилМ
 
07.12.09
11:56
(36)
что такое конечное число проходов O(1)
1 проход ?
38 БТР
 
07.12.09
12:01
Бежим по массиву и добавляем числа в другой массив. При добавлении проверяем содержится ли уже это число в массиве, если содержится то не добавляем и удаляем. Как то так наверное.
39 Ненавижу 1С
 
гуру
07.12.09
12:03
(37) число проходов не зависит от длины массива
(38) нельзя пользоваться памятью, размер которой зависит от размера массива
40 БТР
 
07.12.09
12:04
(39) А сколько памяти можно использовать?
41 Жан Пердежон
 
07.12.09
12:05
(40) в (38) норм с памятью, там число проходов больше О(1)
42 Ненавижу 1С
 
гуру
07.12.09
12:05
(40) O(1) - независимое от размера исходного массива количество
43 Ненавижу 1С
 
гуру
07.12.09
12:06
(41) с памятью тоже не нормально
44 Жан Пердежон
 
07.12.09
12:06
(42) ню-ню
45 Ненавижу 1С
 
гуру
07.12.09
12:07
(44) это ты от безисходности? я сам решения не знаю
46 БТР
 
07.12.09
12:08
Стотыщмильоновгуглионов байт тоже не зависит от исходного массива ибо такой массив не будет заполнен за время жизни вселенной. Сколько вешать в граммах (байтах)?
47 Ненавижу 1С
 
гуру
07.12.09
12:09
(46) не надо крайностей, вы слишком уж взъелись к условиям
48 БТР
 
07.12.09
12:11
Сам подумай. Мы ведь не ограничиваем память на хранение одного числа, значит такая программа всегда будет зависеть от размера массива.
49 Asirius
 
07.12.09
12:13
(4) зачет!
ппц ветка, сразу видно, кто 1С-ник, а кто программист
50 Ненавижу 1С
 
гуру
07.12.09
12:13
(48) например если нужно подсчитать сумму,максимум и среднее массива, то число дополнительной памяти не зависит от размера массива
51 БТР
 
07.12.09
12:27
Есть такой класс математических задач. Я придумал условие, вы попробуйте её решить, а дополнительные условия, я вам потом расскажу, когда вы себе мозг сломаете.
Либо мы решаем теоретическую задачу, тогда (48) и задача решения не имеет, либо практическую и размер целого числа зависит от процессора, тогда (4). Как то так наверное.
52 Ненавижу 1С
 
гуру
07.12.09
12:29
(51) есть такой тип людей, которые понимают условие задачи сразу, а есть, которые нет
53 Ненавижу 1С
 
гуру
07.12.09
12:30
(51) ну решишь ты мою задачу или свою, я медаль тебе все равно не дам, это же форум, а не конкурс
54 smaharbA
 
07.12.09
12:31
(51) d cfl
55 БТР
 
07.12.09
12:33
(52) Я отучился понимать условия задач сразу, потому как озвученные фантазии пользователей никогда не совпадают с ожидаемым ими результатом. Поэтому долблю их по голове до тех пор, пока они сами не поймут чего же они хотят. Сильно экономит время на программирование.
56 БТР
 
07.12.09
12:37
(54) А по теме? Сам то задачу решил? Поделись решением.
57 МихаилМ
 
07.12.09
12:41
Решение через ранжирование для 1 незадвоенного  элемента


1) порбегаемся по таблице,  получаем максимум - минимум

2) создаем таблицу ранжирования (таблицу пападаний интервал)


3) заполняем таблицу
4) ищем в таблице поле  с нечётным количеством

меняем максимум и минимум

повторяем пункты   3) и 4)

пока максимум <> минимум
58 Ненавижу 1С
 
гуру
07.12.09
12:42
(57) но алгоритм не удовлетворяет условиям
59 МихаилМ
 
07.12.09
12:44
(58)
Каким ?
60 Asirius
 
07.12.09
12:44
(34) Если два незвестных в массиве Ai это a и b, то сначала получаем c = a xor b. Потом надо над всем массивом сделать некую операцию F (Ai) = Bi (еще не знаю какую). Потом над массивом Bi снова делаем xor.
На выходе получаем два уравнения, которые по идее должны решиться
с = a xor b
d = F(a) xor F(b)
61 Ненавижу 1С
 
гуру
07.12.09
12:45
(59) число проходов не зависит от размера массива? количество памяти в доп. таблице не зависит от размера массива?
62 skunk
 
07.12.09
12:49
даже юзая ксор число проходов будет зависить от количества элементов массива
63 МихаилМ
 
07.12.09
12:50
(61)
Число проходов зависит от размера таблицы статистики
64 Ненавижу 1С
 
гуру
07.12.09
12:52
(62) число проходов - 1
65 Ненавижу 1С
 
гуру
07.12.09
12:52
(63) ничего не понял
66 skunk
 
07.12.09
12:54
(64)там цикл один ... а ротаций (читай число проходов) будет именно количество элементов массива
67 Ненавижу 1С
 
гуру
07.12.09
12:55
(66) с чего я должен это так считать? проход, это проход, а число итераций действительно O(N)
68 skunk
 
07.12.09
12:57
(67)ну я думал ты как минимум с программированием связан
69 Ненавижу 1С
 
гуру
07.12.09
12:57
(68) а при чем тут это?
70 skunk
 
07.12.09
12:59
(69)открой любой учебник по информатики ... за самые основы программирования и почитай ....

Каждый "проход" цикла называется итерацией.

В отличие от цикла while, этот цикл проверяет значение выражения не до , а после каждого прохода (итерации).
71 Ненавижу 1С
 
гуру
07.12.09
13:01
(70) еще один буквоед, написано же было в (0) "количество проходов О(1)"
72 Ненавижу 1С
 
гуру
07.12.09
13:02
+(70) ошибся, допускаю, условие в (0)
73 МихаилМ
 
07.12.09
13:03
то (65)
N кол-во строк в таблице статистики
тогда  количество проходв <=  log N(максимум - минимум) + 1(первый проход)
и не зависит от размера исходного массива
74 Ненавижу 1С
 
гуру
07.12.09
13:04
(73) ну ты же сам написал "log N"
75 МихаилМ
 
07.12.09
13:07
(74)
Согласен.
Это не "конечное число проходов"
76 Жан Пердежон
 
07.12.09
14:21
(45) да затупил, вместо O(1),про O(n) подумал
вариант есть с ушами - блочная сортировка+проход по блокам (не зависит от длинны входной последовательности)
77 Asirius
 
07.12.09
15:28
(34), +(60) в общем решение для двух различных чисел в массиве такое:
1)>Ксорим весь массив A[i], получаем c = X xor Y, где X и Y - искомые числа.
2) По условию c <> 0, смотрим двоичную запись и берем старший значащий бит =1. Пусть он стоит на k месте. Берем  M = 2^k.
3)Заметим, что
либо
X and M = 0 ; Y and M = М
либо
X and M = М ; Y and M = 0.

4) Преобразуем весь массив B[i] = (A[i] and M)/M * A[i].
тогда Xor массива B[i]  в силу заметки 3) будет равен или X или Y, т.к. одно из них в результате преобразования останется неизменным, а другое обнулится
78 Ненавижу 1С
 
гуру
07.12.09
15:32
(77) 4 пункт не понял сходу
79 Asirius
 
07.12.09
15:34
(77) в принципе, доп память ненужна, достаточно 2 прохода
80 Asirius
 
07.12.09
15:37
(78) во что превратятся другие числа - не важно. Их было по 2 шт., и результатов тоже будет по 2 шт, на конечный xor ини не повлияют.
Важно, что один из X или Y просто обнулиться, а другой нет
81 NS
 
07.12.09
15:44
(78) Это решение подходит, или нужно другое?
Есть другое, черз нахождение среднего значения, подсчет количества элементов больше (и меньше его), отбора той части в которой находится единственное, и т.д.
Сложность алгоритма - N+N/2+N/4...=2N, то есть О(N)
82 Ненавижу 1С
 
гуру
07.12.09
15:45
(80)(81) надо проверить
83 NS
 
07.12.09
15:47
(82) А чего проверять? и так понятно что отксорить даст искомое, и мой вариант тоже даст искомое. И в обоих случаях сложность О(N)
84 БТР
 
07.12.09
15:47
(81) в том то и дело, что "и т.д." (0) же хочет, что бы количество проходов не зависило от N
85 Asirius
 
07.12.09
15:48
Кста, в (0) условие про доп память - лишнее.
Как можно использовать доп памяти больше, чем O(N), за количество операций, не более чем O(N)?
86 Asirius
 
07.12.09
15:51
+(85) млин. Там как раз операций O(N), а памяти O(1).
87 NS
 
07.12.09
15:51
(84) количество проходов массива, а сложность прохода одного прохода - О(N)
соответственно алгоритм с такой сложностью можно считать алгоримом за конечное число проходов.
88 Asirius
 
07.12.09
15:52
(87) а количество доп памяти сколько потребуется?
89 NS
 
07.12.09
15:53
(88) Максимум N элементов, в среднем N/2
90 Asirius
 
07.12.09
15:54
(89) а в условии О(1)
91 NS
 
07.12.09
15:54
(+89) Сначала перебрасываем из начального массива в дополнительный, потом обратно. И т.д.
92 NS
 
07.12.09
15:55
(90) Ну тогда только ксорить.
93 NS
 
07.12.09
15:58
Есть еще вариант - воспользоваться куском квиксорта находящим медиану...
94 TheNewOne
 
07.12.09
16:10
(77) въехал. круто! респект, если сам!
только я бы по другому описал!
пусть искомые X и Y
1)первый проход ксорим все элементы получаем Z = Х^Y
2)Получаем младший бит U = ((Z ^ (Z-1)) + 1) / 2 (вахаха, люблю побитовые операции)
3)второй проход ксорим только те элементы, которые (A[i] & U) != 0. Получаем X!
4)Y = X ^ Z
95 NS
 
07.12.09
16:15
(94) Ничего не понял. XOR всего массива в один проход даст искомый элемент.

Х=0;
Для а=1 по N цикл
Х=Х XOR Масс[а]
Конеццикла;
сообщить(X) - искомый элемент.
96 TheNewOne
 
07.12.09
16:18
(95) - мы решаем с двумя неизвестными, т.е. задачу (34)
97 NS
 
07.12.09
16:35
(96) Понял.
98 TheNewOne
 
07.12.09
16:35
(субьективно) Забавное наблюдение. В этой ветке мне показалось, что персонажи с латинскими никами более подкованы в области общего программирования, нежели персы с русскими никами. В частности, фаворитами задач (0) и (34) являются Rie и Asirius. Случайность или закономерность? Может, это результат привычки давать переменным латинские имена? :) не бейте палками :)
99 Жан Пердежон
 
07.12.09
19:01
(99) в 1 строку написал бы: "у меня ник латиницей, значит я тоже крутой"
100 Ненавижу 1С
 
гуру
07.12.09
21:59
сотня типа
101 NcSteel
 
07.12.09
22:01
Запросом.
102 Stillcat
 
08.12.09
09:06
(77)
На самом деле
Xor массива B[i]  в силу заметки 3) будет равен M, т.к. одно из них в результате преобразования станет М, а другое обнулится
103 Stillcat
 
08.12.09
09:12
+(102)
Или я что-то с преобразованием недопонял?
104 TheNewOne
 
08.12.09
09:23
(103) все так
B[i] составлен только из числел, имеющих один конкретный бит; остальные занулены. среди них будет либо X либо Y, и какое-то количество пар.
105 Asmody
 
модератор
08.12.09
09:34
мне нравится в ваши рассуждениях пунктик "возьмем первый ненулевой старший/младший бит". ага, прям руками и возьмем. но это мелочи.
усложним задачу: условия (0), в языке нет битовых операций
106 Ненавижу 1С
 
гуру
08.12.09
09:38
107 TheNewOne
 
08.12.09
09:39
(105) почему нет?
а с побитовыми операциями младший бит (точнее число только с младшим битом) добывается несложно
108 Asmody
 
модератор
08.12.09
09:46
(106) я имел ввиду - решить эту задачу без битовых операций вообще
109 TheNewOne
 
08.12.09
09:50
(108) а, тфу, спросоня не могу прочитать
110 Rie
 
08.12.09
09:52
(105) +, -, *, /, % - есть?
Значит, и побитовые есть.
111 Asmody
 
модератор
08.12.09
09:59
вот так это решается на python:

b=[a[x] for x in xrange(0,len(a)) if a[x] not in a[:x]+a[x+1:]]
112 Rie
 
08.12.09
10:00
(111) И какова сложность этого решения? Соответствует ли она условиям в (0)?
113 Asmody
 
модератор
08.12.09
10:03
(112) сложность этого решения - в одну строчку
114 Rie
 
08.12.09
10:05
(113) По времени и по памяти.
115 Asmody
 
модератор
08.12.09
10:07
(113)+ если серьезно, то с точки зрения _языка_ тут всего 1 цикл. и дополнительная память не выделяется, поскольку xrange() - ленивый генератор. ну а как в трасляторе реализовано взятие слайсов, сложение массивов, и оператор in - дело десятое
116 Rie
 
08.12.09
10:15
(115) Ленивый генератор с этой точки зрения просто "заменяет" расход памяти расходом времени.
При наиболее эффективной реализации в трансляторе _этого генератора_ (без глобальной оптимизации, которую до сих пор мало кто делает) он доблестно потратит len(а) времени на каждом шаге.
117 Asmody
 
модератор
08.12.09
10:19
запустил на массиве 2 млн.-1 элементов (1..1000000..1)
отъел ~50 мегов памяти, атомный проц где-то на 80%, считает уже минут 5... :)
(python 2.5.1)
118 Asmody
 
модератор
08.12.09
10:23
(116) я же говорю - с точки зрения _языка_.
как это реализовано в трансляторе - дело десятое, иначе и для C++ надо будет залезть внутрь какого-нибудь gcc и разбираться, как же там "наоптимизированы" операции работы со списками.
вообще, идеологически, задача в (0) решается совсем просто:
определяем _язык_, в котором задана такая операция над массивом. все - никаких циклов.
119 Rie
 
08.12.09
10:41
(118) Секция - "Математика и алгоритмы". При чём тут язык?
Алгоритмическая сложность от языка не зависит. Даже если в языке есть метод Sort, сортировку он быстрее чем за N log N не сделает.
120 Asmody
 
модератор
08.12.09
10:44
(119) при том, что нельзя пытаться мыслить абстрактно, при этом не выходя за рамки парадигмы.
121 Нуф-Нуф
 
08.12.09
10:45
идите работать
122 Rie
 
08.12.09
10:55
(120) Кто запретил? Надо мыслить абстрактно, надо оценивать сложность алгоритмов - хотя бы для разработки эффективно работающих конструкций высокого уровня. И представлять себе, во что они выливаются.
Ты же при работе с 1С - оцениваешь, какая конструкция будет эффективнее? Или тоже, мысля в рамках парадигмы, использует полный перебор справочника с проверкой условий вместо запроса с условием на индексированный реквизит?
123 Asmody
 
модератор
08.12.09
12:47
(122) 1С ты вообще приплел зря.
вот вы, решая задачу (0) почему-то решили, что взятие элемента массива по индексу имеет скажем так "единичную мощность". с точки зрения языка - это так, с точки зрения реализации - нет. то же самое относится к любой операции. опять же с точки зрения реализации будет важно, какова "природа" этих целых чисел и определены ли над ними битовые операции. я привел пример на питоне, который формально полностью удовлетворяет условию задачи, причем он решает более общую задачу: поиск всех одиночных элементов массива. Кроме того, в том же питоне есть встроенная функция filter(). Если переписать эту строку с ее помощью, то _формально_ вообще ни одного цикла не будет.
124 Rie
 
08.12.09
13:23
(123) Ты условия задачи внимательно прочитал? Там о "единичной мощности" - ни слова. Сказано лишь - за константное число проходов.
В _других_ задачах - могут быть и другие условия. Но это будут уже _другие_ задачи. С, возможно, _другими_ решениями.
125 NS
 
09.12.09
17:44
(123) Сложность алгоритмов это наука. Сложность не зависит от языка и реализации. Зависит только от алгоритма.
126 silent_
stranger
 
10.12.09
14:09
Не знаю, было или нет, но предложение с xor-ами натолкнуло вот на такую мысль:
int i;
int S = 0;
bool flag = true;
for (i = 0; i<= N-1; i++) {
 if (flag)
   S += array[i];
 else
   S -= array[i];
 flag = !flag;
}
Ну а дальше смотрим на знак S. Если отрицательное, то ответ -S, если положительно, то это и есть искомый ответ.
127 Ненавижу 1С
 
гуру
10.12.09
14:13
(126) уверен, что одинаковые не будут с одним знаком?
128 silent_
stranger
 
10.12.09
14:28
(127) Мдя, обломс...
129 upyx
 
11.12.09
06:02
(123) Как бы то ни было, все это будет выполнять не язык, а процессор. Так вот все, известные мне, процессоры умеют xor, а filter() не умет ни один. "Взятие элемента массива по индексу" - всего-лишь пример, чтобы объяснить суть *алгоритма* автору задачи. А там уж автор пуст сам решает как перебирать элементы своего массива. Вы же предлагаете не общий алгоритм (который будет выполнять процессор), а конкретное решение на конкретном языке, что не соответствует условию задачи (0).

(77) (94) А зачем так сложно?
U = ((Z ^ (Z-1)) + 1) / 2 - ну нефига себе...
Если искомые х1 и х2, то:
1) Как в (29) находим r = x1 xor x2;
2) Делаем проверку на каждый элемент массива (a[i]):
 если (r and a[i]) равно a[i], то a[i] есть х1,
 либо: если (r or a[i]) равно r, то a[i] есь х1;
3) x2 = r xor x1;
Кажется так... о.О
130 Salimbek
 
11.12.09
08:06
(129) То есть, при искомых значениях 1100 и 0001 мы получили r=1101. Теперь перебирая массив мы наткнулись на число 1001 - проверка "если (r and a[i]) равно a[i], то a[i] есть х1" - будет им успешно пройдена.
131 upyx
 
11.12.09
10:17
(130) Ну да :) С просони не сообразил.