powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Задачка на собеседовании. Коллекции.
25 сообщений из 42, страница 1 из 2
Задачка на собеседовании. Коллекции.
    #38703182
whizzzkey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приветствую, получил вот такую задачку на собеседовании на Java-junior'a, меня немного ввела в ступор тем что просто перебрать не можем, тогда каким образом искать дубликаты? Если не трудно объясните решение данной задачи. Благодарю.

Дан класс com.noname.User, модифицировать его не можем. Нужно написать утилитный метод
public static List<User> findDuplicates(Collection<User> collA, Collection<User> collB);
который возвращает дубликаты: юзеров, которые есть в обеих коллекциях. Одинаковыми считаем юзеров, у которых совпадают все 3 поля: username, email, passwordHash.
По производительности: метод findDuplicates должен работать не больше нескольких секунд, если на вход получает 2 коллекции по 100 тысяч элементов в каждой. То есть, простой перебор в цикле не подойдёт.
Пользоваться можно только стандартными классами Java SE


public final class User {

private String username;

private String email;

private byte[] passwordHash;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public byte[] getPasswordHash() {
return passwordHash;
}

public void setPasswordHash(byte[] passwordHash) {
this.passwordHash = passwordHash;
}
}
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703218
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Первое что пришло в голову - перегнать обе коллекции в списки, отсортировать со своим компаратором и проделать нечто вроде сортировки слиянием, но отбрасывая пользователей, которых нет в обоих списках.
Второе - преобразовывать юзеров из 1 коллекции в строки (склеить строковые представления всех полей) и запихивать пары строка-юзер в любую Map<String,User>, потом юзеров из 2 коллекции тоже перегонять в строку, смотреть есть ли такой ключ в мапе и если есть, то отдавать в список повторов.
Set-ы не предлагаю, ибо что деревянный что хешевый сделаны через отображения, так что отличий от варианта 2 не будет.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703224
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
whizzzkey,


collA.retainsAll(new HashSet(collB));

а теперь взять исходник retainsAll и if (!c.contains(new _User(it.next())))
и у класса _User написать equal куда передается User
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703295
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Замечания к постановке.

1) Нам уже даны коллекции? Или их нужно наполнять. Во втором случае без перебора всех элементов нам не обойтись. Наполнение коллекции это O(n) сложная задача.

2) Если имплементация коллекции удачно подходит под работу с множествами (объединение вычитание) то можно из первого множества вычесть второе а потом перебрать в первом все кого нет во втором.

removeAll(Collection<?> c)

3) Но здесь подвох. Мы совершенно не знаем сколько будет дубликатов. 1 или сто тыщ и производительность операции вывода результата может быть также O(n) что сводит на нет все оптимизации.

Вообще здесь нужно препарировать моск товарищу который это адское задание придумал.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703306
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ограничение времени - несколько секунд на 100к юзеров, достаточно почти для всего, что лучше O(n^2).
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703309
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может, еще надо уточнить на каком железе это должно работать?

Написал в лоб:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
   
   public static List<User> findDuplicates(Collection<User> collA, Collection<User> collB) {
      List<User> result = new ArrayList<User>();

      TreeSet<User> set = new TreeSet<User>(USER_COMPARATOR);
      set.addAll(collA);

      for (User user : collB) {
         if (set.contains(user)) result.add(user);
      }
      return result;
   }



При 100000 элементов в каждой коллекции затрачивается около 0.3с. Причем сначала ошибся, и вместо set.contains написал collA.contains . Результат был около 4с, что тоже отвечает условиям.
collA и collB -- ArrayList
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703329
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Навеяло опечаткой с collA.contains . Похоже, джавадоки-то врут. Про метод TreeSet.contains сказано:

джавадокreturns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
Однако для TreeSet c компаратором условие другое: comparator.compareTo(o, e)==0 .

И чтобы два раза не вставать.
Совсем тупой вложенный цикл по двум коллекциям занял около 220с.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703612
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Автор просил объяснить, между тем видим либо только решения, либо даже критику постановки задачи (для джуниора это недопустимо).
Между тем, все достаточно просто.
1) Решение в лоб - вложенный перебор коллеций, сложность O(n 2 )
Допустим, сравнение двух объектов в среднем займет 100 тактов, получаем:
100*100000*100000 = 10 12 тактов, при частоте 3*10 9 получаем порядка 300 секунд, явно не укладываемся в условия. Возможны различные оптимизации, но существенно от O(n 2 ) они не спасут
2) используем знания джуниора о коллекциях.
Джуниор должен знать, что для поиска дубликатов хорошо подходят множества, и наиболее эффективный поиск реализован в HashSet (O(1)), что позволит найти дубликаты за время O(n). Можно также использовать TreeSet с временем поиска O(ln(n)), что даст решение со сложностью O(n*ln(n)), но давайте сосредоточимся на первом варианте.
Для него нам не хватает методов, которые не были реализованы в изначальном классе: equals() и hashCode(). Решение - унаследовать изначальный класс, либо "обернуть", и там реализовать недостающие методы. Так как изначальный класс объявлен final, остается только возможность обертки:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class _User {
  public final User user;
  public _User(User user) {
    this.user=user;
  }
  @Override
  public boolean equals(Object object) {
    ...сравниваем внутренних user-ов
  }
  @Override
  public int hashCode() {
    ... вычисляем хеш из user-а
  }
  // для оптимизации тут можно добавить приватное поле hash, и выислять его только 1 раз, например, в конструкторе
}



Далее заполняем 2 множества объектами _User, находим дубликаты, используя операци над множествами, извлекаем из них исходные экземпляры User.

Прикинем расходы.
Память:
Допустим, объект класса _User (указатель на User, поле hash), а также расходы на его хранение в таблице составять порядка 100 байт. Таким образом, для хранения 2 вспомогательных множеств понадобится дополнительная память порядка 2*100*100000 ~ 20 мб
Время:
Допустим, итерация по исходной коллекции, создание объекта и вычисление хеша потребует порядка 1000 тактов. Тогда для заполнения 2 множеств потребуется 2*1000*100000 = 2*10 8 тактов, при частоте при частоте 3*10 9 получаем меньше 0.1 секунды.
Сам поиск займет O(n), тут сложно говорить о величине этого O, но в реальности оно небольшое. Допустим, 10 4 тактов. В этом случае весь поиск займет порядка 10 9 тактов, или меньше секунды.

Наиболее тонкий момент тут - написать хорошую хеш-функцию. Используем простые числа, либо берем из какой-нибудь библиотеки, например, apache commons
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38703814
whizzzkey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Благодарю всех за ответы!
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706161
mbiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Во блин, моя задачка на родной sql.ru попала, приятно :)
Вообще, мы ищем синьора. Надо будет с HR поругаться, что вводят соискателей в заблуждение.
ivanra предельно точно и полно объяснил решение, и добавить нечего.
Или хеш (какой нибудь HashSet + определить методы equals и hashCode), или упорядоченный поиск (TreeSet + кастомный компаратор). Оба решения принимаются. Хотя, если человек предлагает второй вариант (TreeSet), я начинаю относиться к нему с подозрением.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706240
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
whizzzkey,

автордолжен работать не больше нескольких секунд,

-- это интересный критерий ! Ещё никогда о таких подходах не слышал.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706275
mbiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я не спец в этом вопросе. Но вот набрал в поиске: http://goo.gl/zU47xh
Верхние два результата
авторКубок ОАО ``Концерн ``НПО ``Аврора'' по программированию (что бы это ни значило)
Пример задачи
Задано целое число n. Требуется найти число различных делителей n.
На ввод подается целое число n (1 ≤ n ≤ 109).
Следует вывести число различных делителей n.
Ограничения по времени: 0.1 сек.
Ограничения по памяти: 64 мегабайта.авторПравила Четырнадцатой Всероссийской командной олимпиады школьников по программированию
Жюри указывает ограничения на время работы программы на одном тесте и на размер доступной памяти в формулировках задач.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706277
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivwhizzzkey,

автордолжен работать не больше нескольких секунд,

-- это интересный критерий ! Ещё никогда о таких подходах не слышал.
Там несколько секунд будет ClassLoader будет прогружать деревище классов.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706283
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто чтобы уточнить - "ищем синьора", но один из критериев - знает ли он хоть что-то о явовских коллекциях?
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706294
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Синьор не станет разговаривать на собеседовании о коллекциях.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706302
mbiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wstПросто чтобы уточнить - "ищем синьора", но один из критериев - знает ли он хоть что-то о явовских коллекциях?

Типа того. Незатратный для меня по времени способ провести первичный отсев. Многие соискатели, даже имеющие в резюме 10+ лет опыта разработки на Java, не справляются с этой детской задачкой на 20 минут (это если ещё и тесты писать).
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706307
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mbiz Типа того. Незатратный для меня по времени способ провести первичный отсев. Многие соискатели, даже имеющие в резюме 10+ лет опыта разработки на Java, не справляются с этой детской задачкой на 20 минут (это если ещё и тесты писать).
м-да.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706382
private
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На собеседовании (по JavaScript правда, не по Java) преподаватель вуза или колледжа какого-то который преподавал для студентов веб программирование с многолетним опытом, и убедительным рассказом об опыте работы - не смог написать реализацию метода map :)
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706391
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonСиньор не станет разговаривать на собеседовании о коллекциях.А о чем сеньер будет разговаривать?
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706392
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvmaytonСиньор не станет разговаривать на собеседовании о коллекциях.А о чем сеньер будет разговаривать?

Зп, обеды, личный водитель.. все как обычно :)
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706553
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
privatemap :)
стесняюсь спросить, что делает метод map? карту гугла показывает?
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706556
mbiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Поправил немного описание:
бла-бла ... у которых совпадают все 3 поля: username, email, passwordHash.
Пользоваться можно только стандартными классами Java SE версии не выше 7 (восьмёрку я ещё ниасиливал, да и пока мало она в реальных проектах используется).
Алгоритм должен быть реализован более эффективно, чем простой перебор. В качестве приблизительного критерия можно использовать условие, что метод findDuplicates должен работать не больше нескольких секунд, если на вход получает 2 коллекции по 100 тысяч элементов в каждой. Мой вариант решения, поправьте, если он не совершенен :)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
package com.noname;

import java.util.*;

public class UserUtils {

    public static List<User> findDuplicates(Collection<User> collA, Collection<User> collB) {
        if (collA == null || collB == null) {
            return Collections.emptyList();
        }

        Set<UserWrapper> wrapperSetB = new HashSet<>(collB.size());
        for (User userB : collB) {
            wrapperSetB.add(new UserWrapper(userB));
        }

        Set<UserWrapper> wrapperDuplicates = new HashSet<>();

        for (User userA : collA) {
            UserWrapper sample = new UserWrapper(userA);
            if (wrapperSetB.contains(sample)) {
                wrapperDuplicates.add(sample);
            }
        }

        List<User> duplicates = new ArrayList<>(wrapperDuplicates.size());
        for (UserWrapper wrapper : wrapperDuplicates) {
            duplicates.add(wrapper.user);
        }

        return duplicates;
    }

    private static class UserWrapper {

        final User user;

        UserWrapper(User user) {
            this.user = user;
        }

        @Override
        public int hashCode() {
            return hashCode(user.getUsername()) * 633910099
                    + hashCode(user.getEmail()) * 160481183
                    + Arrays.hashCode(user.getPasswordHash());
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof UserWrapper)) {
                return false;
            }
            User u = ((UserWrapper) obj).user;
            return equal(user.getUsername(), u.getUsername()) && equal(user.getEmail(), u.getEmail())
                    && Arrays.equals(user.getPasswordHash(), u.getPasswordHash());
        }

        static boolean equal(Object o1, Object o2) {
            return o1 == o2 || (o1 != null && o1.equals(o2));
        }

        static int hashCode(Object o) {
            return o == null ? 961748941 : o.hashCode();
        }
    }

    private static final int NUMBER_OF_USERS = 100000;
    private static Random RANDOM = new Random();

    public static void main(String[] args) {
        List<User> listA = new ArrayList<>(NUMBER_OF_USERS);
        List<User> listB = new ArrayList<>(NUMBER_OF_USERS);

        for (int i = 0; i < NUMBER_OF_USERS; i++) {
            User userA = newUser();
            listA.add(userA);

            listB.add(newUser());

            if (i % 1000 == 0) {
                // Добавим дубликат.
                User userB = new User();
                userB.setUsername(userA.getUsername());
                userB.setEmail(userA.getEmail());
                userB.setPasswordHash(Arrays.copyOf(userA.getPasswordHash(), userA.getPasswordHash().length));
                listB.add(userB);
            }
        }

        long stamp = System.currentTimeMillis();

        List<User> dups = findDuplicates(listA, listB);

        System.out.println(dups.size() + " " + (System.currentTimeMillis() - stamp) / 1000d);
    }

    private static User newUser() {
        User user = new User();

        user.setUsername(Math.random() + "");
        user.setEmail(Math.random() + "");

        byte[] bytes = new byte[32];
        RANDOM.nextBytes(bytes);
        user.setPasswordHash(bytes);

        return user;
    }
}
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706558
mbiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Из кода можно подчерпнуть много информации помимо собственно правильно/неправильно решил. В код профессионала можно даже не вчитываться, сразу всё понятно просто по форматированию, именованию переменных и другим признакам. И наоборот, если "школьник" перед собеседованием случайно решал аналогичную задачу, и даже выдал правильное решение, код его обязательно выдаст.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706628
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А можно еще увидеть код того самого профессионала? То есть, в числе прочего, человека, способного задуматься что это за пользователи, различающиеся только паролями и что если это не подвох в задаче, а реальное требование, то неплохо бы хоть как-то этот момент прояснить в комментариях.
...
Рейтинг: 0 / 0
Задачка на собеседовании. Коллекции.
    #38706670
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторне справляются с этой детской задачкой на 20 минут (это если ещё и тесты писать).
ВСЁ ИМХО: я что-то сомневаюсь, что Вы успеете за двадцать минут с ходу сделать. А мы то знаем как подобные здачки появляются на свет. Группа прогеров натыкается на проблему, несколько часов (не постесняюсь, даже дней!) пытаются сделать хоть что-то, потом еще столько же отлаживают, а потом на собеседовании просят за 20 мин. на листе бумаги накодить. Неадекват реально. Понимаю если-б какой нить микрософт или оракл хотя бы такое устраивал, а так ваще!
...
Рейтинг: 0 / 0
25 сообщений из 42, страница 1 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / Задачка на собеседовании. Коллекции.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]