우테코5기 프리코스 1주차 Problem6

@hongo · November 02, 2022 · 2 min read

Problem6 : 닉네임 중복 체크

prob6

📗 기능 목록

📌 checkOverlapOfWord
한 nickname안의 두 글자 이상이 중복되는지를 체크

📌 checkOverlap
nickname들이 중복인지를 체크

📌 getOverlapNicknames
중복되는 nickname들의 리스트를 반환

📌 코드

깃허브 코드

	/**
     * nickname이 두 글자 이상 중복이 아니라면 wordOfNickname에 삽입, 중복된다면 중복되는 nickname의 index를 반환
     * @param nickname 중복을 검사할 nickname
     * @param index nickname의 index
     * @return nickname이 중복이 아니라면 -1, 중복이라면 중복되는 nickname의 index
     */
    int checkOverlapOfWord(String nickname, Integer index){
        for(int i = 0; i<nickname.length()-1; i++){
            String target = nickname.substring(i, i+2);
            if(wordOfNickname.containsKey(target) && wordOfNickname.get(target) != index){
                return wordOfNickname.get(target);
            }
            wordOfNickname.put(target, index);
        }
        return -1;
    }

    /**
     * form에 있는 nickname들이 중복인지 아닌지를 체크
     */
    void checkOverlap(){
        for(int i = 0; i<forms.size(); i++){
            List<String> form = forms.get(i);
            String nickname = form.get(1);
            int overlapIndex = checkOverlapOfWord(nickname,i);
            if(overlapIndex != -1){
                isOverlap[overlapIndex] = true;
                isOverlap[i] = true;
            }
        }
    }
  • 닉네임을 두 글자씩 나눈 word가 중복되지 않는다면 wordOfNickname해시맵에 key로 저장한다.
  • 이후 다른 사람의 닉네임을 이루는 word와 같은 word가 wordOfNickname에 key로 존재한다면, 해당 word는 중복이라는 의미이므로, 두 닉네임이 중복임을 체크한다.

✏ 다른 분의 풀이

mihye126님의 허락을 받고 슬랙에 공유해주신 풀이를 가져왔다.

private static List<String> tokenizer(String str) {
        return IntStream.rangeClosed(0, str.length() - 2)
            .mapToObj(i -> String.join("", Arrays.copyOfRange(str.split(""), i, i + 2)))
            .collect(Collectors.toList());
    }
  • Stream API을 사용해 닉네임을 두 글자씩 나누는 메소드이다.

해당 문제와 같이 트래픽이 적은 경우는 Stream을 사용하면 가독성있게 처리할 수 있다. (트래픽이 많을 경우에는 traditional for-loop를 사용하는 것이 효율성면에서 좋다고 한다. 참고 : java-stream-api는-왜-for-loop보다-느릴까)

Stream에 대한 지식이 없어 이런 풀이 방법은 생각하지 못했는데 가독성이 뛰어난 좋은 방법인 것 같다.


public static List<String> solution(List<List<String>> forms) {
        //key: token / value: email
        HashMap<String, HashSet<String>> userMap = new HashMap<>();

        for (List<String> form : forms) {
            String nickname = form.get(1);
            String email = form.get(0);
            List<String> tokens = tokenizer(nickname);
            tokens.forEach(token -> appendMapValue(token, email, userMap));
        }

        List<String> entries = userMap.entrySet().stream()
            .filter(item -> item.getValue().size() > 1) //token에 이메일이 2개 이상이면 추출
            .flatMap(item -> item.getValue().stream())//value값인 email만
            .sorted()//정렬하기
            .collect(Collectors.toList());    //stream to list

        return entries;
    }
}
  • 이후 userMap [nicknameToken] ={email1, email2, ...} 에서도 Stream을 사용해 중복 닉네임을 가진 이메일만 필터하는 것을 볼 수 있다.
@hongo
홍고 블로그