코딩테스트

[Programmers] 오픈채팅방

728x90

programmers.co.kr/learn/courses/30/lessons/42888

 

코딩테스트 연습 - 오픈채팅방

오픈채팅방 카카오톡 오픈채팅방에서는 친구가 아닌 사람들과 대화를 할 수 있는데, 본래 닉네임이 아닌 가상의 닉네임을 사용하여 채팅방에 들어갈 수 있다. 신입사원인 김크루는 카카오톡 오

programmers.co.kr

실무에서도 유용하게 쓸 것 같은 문제라 골랐다. 무엇보다 문제 자체가 재밌어 보였다. 😎

분명히 수도코드 차근차근 짜서 잘했다고 생각했는데, 뭐가 문제였는지 메인 테스트 코드 이외에는 실패 떴다.

그래서 고치고 고쳤는데 배열 값을 출력했을 때는 잘 나오던 값이 안나와서 속이 답답했음..

결국 새 배열을 만들어줬더니 잘 작동했다.

마음처럼 쉽지 않은 코테


첫 풀이

public String[] solution(String[] record) {
        // answer 배열 개수는 enter + leave 개수
        int count = 0;
        String[] answer = new String[record.length];

        // {아이디 :닉네임} 저장을 위해 map 선언
        Map<String, String> map = new HashMap<>();

        // 각 record 문자열을 공백으로 split
        for (int i=0;i<record.length;i++) {
            String oneRecord = record[i];
            String[] split = oneRecord.split(" ");

            //보기 쉽게 변수로 선언
            String command = split[0];
            String uid = split[1];
            String nickName = "";

            if (split.length > 2) {
                nickName = split[2];
            }

            // 이미 map에 저장되어 있다면
            if(map.get(uid)!=null){
                if (command.equals("Leave")) {
                    answer[count] = uid + "님이 나갔습니다.";
                    count++;
                } else {
                    map.put(uid, nickName);
                    if (command.equals("Enter")){
                        answer[count] = uid + "님이 들어왔습니다.";
                        count++;
                    }
                    // 배열에서 아이디(key)로 닉네임 찾아서 변경
                    for(int j=0;j<count;j++){
                        int idx = answer[j].indexOf("님");
                        String id = answer[j].substring(0, idx);
                        if(id.equals(uid)){
                            answer[j] = answer[j].replace(uid, map.get(uid));
                        }
                    }
                }// if
            }else{
                map.put(uid, nickName);
                answer[count] = uid + "님이 들어왔습니다.";
                count++;
            }
        } //for

        //배열에 null값 없애기
        answer = Arrays.copyOf(answer, count);

        return answer;
    }
}

고유한 uid 값을 이용해야하므로 배열에는 uid 로 저장했다.

처음에 값을 다 넣어준 채로 바꾸려니, uid 값을 키로 사용할 수가 없어서 정체..

배열에서 아이디로 닉네임 찾아서 변경해줄 때, 마지막 출력전에도 바꿔줘야하는데 위 코드의 for문 조건이 부실했다.

그래서 테스트 케이스 하나는 통과해도 전체 로직은 미완..

 

 

풀이 (수정)

    public String[] solution(String[] record) {
        // answer 배열 개수는 enter + leave 개수
        int count = 0;
        String[] answer = new String[record.length];

        Map<String,String> map = new HashMap<>();

        // 각 record 문자열을 공백으로 split
        for (String chat : record) {
            String[] split = chat.split(" ");

            //보기 쉽게 변수로 선언
            String command = split[0];
            String uid = split[1];
            String nickName = "";
            if (split.length > 2) {
                nickName = split[2];
            }

            if (command.equals("Enter")) {
                answer[count] = uid + "님이 들어왔습니다.";
                count++;
            }else if(command.equals("Leave")) {
                answer[count] = uid + "님이 나갔습니다.";
                count++;
            }

            if(nickName!=null && !nickName.isEmpty()){
                map.put(uid,nickName);
            }

        } //for

        //배열에 null값 없애기
        answer = Arrays.copyOf(answer, count);
        
        //새로운 배열에 저장
        String [] result = new String[count];
        for(int i=0;i<count;i++){
            String chat = answer[i];
            int idx = chat.indexOf("님");
            String id = chat.substring(0,idx);
            String changed = chat.replace(id, map.get(id));
            result[i] = changed;
        }

        return result;
    }

배열의 길이가 달라서 길이를 바꿔줄때 Arrays.copyOf(배열, 새로운길이); 를 사용해봤다.

 

그리고 String 배열 result를 새로 선언해서 바꾼 값들을 넣어줬다. 

새로 선언하지 않고, 기존 answer 만 사용하면 프린트로 출력했을때 바뀐 것 같아도 바뀌지 않는다.

해시코드도 확인을 했는데 왤까..? 어쩃든 새로운 배열에 바뀐값들을 넣어 return 해서 완성했다.

 

🔍 기존 answer만 사용했을 때, 리턴된 answer 값이 바뀌지 않았던 이유 !!!

더보기

확장 for문을 쓰게되면 이미 새로운 String 변수에 저장된 것
예 : for(String chat : answer)

즉, answer[i] 가 바뀌는 것이 아니라 answer[i]의 복제값인 새로운 String 값이 변화하는 것이므로, answer[i] 자체를 바꾸려면 개별 요소를 나타내는 변수 i가 필요하다.

 

따라서 확장 for를 쓰지 않고 answer[i] 를 직접 바꿔주는 코드로 바꾸면 result 배열을 새로 선언하지 않아도 풀 수 있다. 

    public String[] solution(String[] record) {
        // answer 배열 개수는 enter + leave 개수
        int count = 0;
        String[] answer = new String[record.length];

        Map<String,String> map = new HashMap<>();

        // 각 record 문자열을 공백으로 split
        for (String chat : record) {
            String[] split = chat.split(" ");

            //보기 쉽게 변수로 선언
            String command = split[0];
            String uid = split[1];
            String nickName = "";
            if (split.length > 2) {
                nickName = split[2];
            }

            if (command.equals("Enter")) {
                answer[count] = uid + "님이 들어왔습니다.";
                count++;
            }else if(command.equals("Leave")) {
                answer[count] = uid + "님이 나갔습니다.";
                count++;
            }

            if(nickName!=null && !nickName.isEmpty()){
                map.put(uid,nickName);
            }

        } //for

        //배열에 null값 없애기
        answer = Arrays.copyOf(answer, count);
        
        for(int i=0;i<count;i++){
            int idx = answer[i].indexOf("님");
            String id = answer[i].substring(0,idx);
            answer[i] = answer[i].replace(id, map.get(id));
        }

        return answer;
    }

 

728x90

'코딩테스트' 카테고리의 다른 글

[BAEKJOON] 1302. 베스트셀러  (0) 2021.03.27
[LeetCode] 21. Merge Two Sorted Lists  (0) 2021.03.25
[Programmers] 카펫  (0) 2021.03.24
[Programmers] 주식가격  (0) 2021.03.23
[LeetCode] 169. Majority Element  (4) 2021.03.19