11import java .io .BufferedInputStream ;
22import java .io .IOException ;
33import java .io .InputStream ;
4+ import java .util .OptionalInt ;
45
5- // https://contest.yandex.ru/contest/24414/run-report/160043341 /
6+ // https://contest.yandex.ru/contest/24414/run-report/160371601 /
67
78public class Map {
89
@@ -12,26 +13,38 @@ public class Map {
1213 * Есть массив бакетов. В каждом бакете лежит связный список элементов.
1314 *
1415 * Для ключа key:
15- * - считаем номер бакета;
16+ * - считаем номер бакета по формуле key % SIZE;
17+ * если остаток отрицательный, прибавляем SIZE,
18+ * чтобы индекс был в диапазоне от 0 до SIZE - 1;
1619 * - идём по списку этого бакета;
17- * - put: если ключ нашли, обновляем значение, иначе добавляем новый узел;
20+ * - put: если ключ нашли, обновляем значение, иначе
21+ * добавляем новый узел в начало списка бакета:
22+ * buckets[i] = new Node(key, value, buckets[i]);
1823 * - get: если нашли, выводим значение, иначе None;
19- * - delete: если нашли, удаляем узел и выводим значение, иначе None.
24+ * - delete: если нашли, удаляем узел из списка:
25+ * если удаляется голова, делаем buckets[i] = cur.next,
26+ * иначе делаем prev.next = cur.next.
2027 *
2128 * Почему алгоритм корректен:
22- * - Каждый ключ всегда попадает в один и тот же бакет.
29+ * - Каждый ключ всегда попадает в один и тот же бакет,
30+ * потому что функция index(key) зависит только от key и SIZE.
2331 * - Все элементы этого бакета хранятся в одном списке.
2432 * - Поэтому, если пройти весь список, мы точно:
2533 * - найдём ключ, если он есть;
2634 * - поймём, что его нет, если не нашли.
2735 *
2836 * Временная сложность:
29- * - put, get, delete — O(1) в среднем.
30- * - В худшем случае — O(s), где s — число элементов в таблице,
31- * если все ключи попали в один бакет.
37+ * - одна операция put, get или delete в среднем работает за O(1);
38+ * - в худшем случае одна операция работает за O(n),
39+ * если все ключи попали в один бакет;
40+ * - так как выполняется n команд, суммарная сложность программы
41+ * в среднем O(n), в худшем случае O(n^2).
3242 *
3343 * Пространственная сложность:
34- * - O(m + s), где m — число бакетов, s — число элементов в таблице.
44+ * - в худшем случае таблица хранит до n элементов,
45+ * поэтому пространственная сложность O(n);
46+ * - массив бакетов имеет фиксированный размер SIZE,
47+ * то есть даёт только константную добавку.
3548 */
3649
3750 private static final int SIZE = 100_003 ;
@@ -74,21 +87,21 @@ void put(int key, int value) {
7487 buckets [i ] = new Node (key , value , buckets [i ]);
7588 }
7689
77- String get (int key ) {
90+ OptionalInt get (int key ) {
7891 int i = index (key );
7992 Node cur = buckets [i ];
8093
8194 while (cur != null ) {
8295 if (cur .key == key ) {
83- return String . valueOf (cur .value );
96+ return OptionalInt . of (cur .value );
8497 }
8598 cur = cur .next ;
8699 }
87100
88- return "None" ;
101+ return OptionalInt . empty () ;
89102 }
90103
91- String delete (int key ) {
104+ OptionalInt delete (int key ) {
92105 int i = index (key );
93106 Node cur = buckets [i ];
94107 Node prev = null ;
@@ -100,13 +113,13 @@ String delete(int key) {
100113 } else {
101114 prev .next = cur .next ;
102115 }
103- return String . valueOf (cur .value );
116+ return OptionalInt . of (cur .value );
104117 }
105118 prev = cur ;
106119 cur = cur .next ;
107120 }
108121
109- return "None" ;
122+ return OptionalInt . empty () ;
110123 }
111124 }
112125
@@ -179,9 +192,11 @@ public static void main(String[] args) throws Exception {
179192 int value = reader .nextInt ();
180193 table .put (key , value );
181194 } else if (command == 'g' ) {
182- out .append (table .get (key )).append ('\n' );
195+ table .get (key ).ifPresentOrElse (out ::append , () -> out .append ("None" ));
196+ out .append (System .lineSeparator ());
183197 } else {
184- out .append (table .delete (key )).append ('\n' );
198+ table .delete (key ).ifPresentOrElse (out ::append , () -> out .append ("None" ));
199+ out .append (System .lineSeparator ());
185200 }
186201 }
187202
0 commit comments