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

 

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

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

programmers.co.kr

문제 풀이 (JAVA) -  효율성 테스트(25~32) 실패 코드

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class OpenChatFailed {

	public static void main(String[] args) {
		// 오픈채팅방(효율성25~32 실패 코드)
	}

	class User {
		String id;
		String name;
		String message;

		User(String id, String name, String message) {
			this.id = id;
			this.name = name;
			this.message = message;
		}

		void set(String name, String message) {
			this.name = name;
			this.message = message;
		}
	}

	public String[] solution(String[] record) {
		String[] answer = {};
		String enter = "님이 들어왔습니다.";
		String quit = "님이 나갔습니다.";
		int idxcnt = 0;
		List<User> list = new ArrayList<>(); // 모든 기록 리스트
		List<String> change = new ArrayList<>(); // Leave와 Change 리스트
		for (int i = 0; i < record.length; i++) {
			StringTokenizer token = new StringTokenizer(record[i], " ");
			idxcnt = token.countTokens();
			String[] str = new String[idxcnt];
			for (int j = 0; j < idxcnt; j++) {
				str[j] = token.nextToken();
			}
			if ("Enter".equals(str[0]) == true) {
				String userId = str[1];
				String name = str[2];
				String message = name + enter;
				if (list.size() > 0) {
					for (int k = 0; k < list.size(); k++) {
						if (userId.equals(list.get(k).id)) {
							String beforename = list.get(k).name;
							String msg = list.get(k).message;
							msg = msg.replace(beforename, name);
							list.get(k).set(name, msg);
						}
					}
				}
				User user = new User(userId, name, message);
				list.add(user);
			} else if ("Leave".equals(str[0]) == true) {
				String name = "";
				for (int k = 0; k < list.size(); k++) {
					if (str[1].equals(list.get(k).id)) {
						name = list.get(k).name;
					}
				}
				change.add(str[0] + " " + str[1]);
				String userId = str[1];
				String message = name + quit;
				User user = new User(userId, name, message);
				list.add(user);
			}
			if (list.size() > 0 && "Change".equals(str[0])) {
				change.add(str[0] + " " + str[1] + " " + str[2]);
				for (int k = 0; k < list.size(); k++) {
					if (str[1].equals(list.get(k).id)) {
						String newname = str[2];
						String msg = list.get(k).message;
						String name = list.get(k).name;
						msg = msg.replace(name, newname);
						list.get(k).set(newname, msg);
					}
				}
			}
		}
		answer = new String[list.size()];
		for (int i = 0; i < list.size(); i++) {
			answer[i] = list.get(i).message;
		}
		return answer;
	}
}

 

이전 코드 리뷰

:효율성테스트가 실패한 이유는 record의 개수가 10만개까지 나올수 있기 때문이다. 해당 코드로 풀었을 경우 list의 사이즈를 반복하여 수정하기 때문에 O(n)이 아닌 O(n^2) 이상의 반복을 통해 안 좋은 효율이 나온다. 그렇기 때문에 이 코드는 대량의 record가 들어왔을때를 처리하기 힘든 코드이다.

 

 

문제 풀이 (JAVA) -  효율성 테스트 성공

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

public class OpenChatSuccess {

	public static void main(String[] args) {
		// 오픈채팅방(성공,HashMap사용)

	}

	// 유저 정보 클래스 생성
	class User {
		String id; // 아이디
		String name; // 닉네임
		String message; // 메세지
		String what; // Enter, Leave
		// 생성자 클래스 선언

		User(String id, String name, String message, String what) {
			this.id = id;
			this.name = name;
			this.message = message;
			this.what = what;
		}

		// setter 메소드 생성(닉네임,메세지)
		void set(String name, String message) {
			this.name = name;
			this.message = message;
		}
	}

	public String[] solution(String[] record) {
		String[] answer = {};
		String enter = "님이 들어왔습니다.";
		String quit = "님이 나갔습니다.";
		int idxcnt = 0; // 문자열 토큰 숫자 변수
		List<User> list = new ArrayList<>(); // 모든 기록 리스트
		HashMap<String, String> map = new HashMap<>(); // id와 name 저장
		for (int i = 0; i < record.length; i++) {
			// 각 행을 공백을 기준으로 문자열 토큰으로 저장
			StringTokenizer token = new StringTokenizer(record[i], " ");
			idxcnt = token.countTokens();
			String[] str = new String[idxcnt]; // 문자열 배열에 재선언
			for (int j = 0; j < idxcnt; j++) {
				str[j] = token.nextToken();
			}
			// 입장했을 시 유저정보를 User 클래스에 저장
			if ("Enter".equals(str[0]) == true) {
				String userId = str[1];
				String name = str[2];
				String message = name + enter;
				map.put(userId, name); // 유저ID의 네임정보 변경 혹은 생성
				User user = new User(userId, name, message, str[0]);
				list.add(user);
			}
			// 퇴장시 닉네임은 없으므로 아이디와 메세지만 저장.
			else if ("Leave".equals(str[0]) == true) {
				String name = "";
				String userId = str[1];
				String message = name + quit;
				User user = new User(userId, name, message, str[0]);
				list.add(user);
			}
			// 변경 시 유저ID의 네임정보 변경
			else if ("Change".equals(str[0])) {
				map.put(str[1], str[2]);
			}
		}
		// 변경 처리를 위한 for문(효율성 테스트 문제로 저장과 변경을 나누어야 함)
		for (int i = 0; i < list.size(); i++) {
			// 유저클래스 아이디 정보가 해쉬맵의 아이디에 있다면
			if (map.containsKey(list.get(i).id)) {
				// 입장시 저장한 문자열 닉네임 정보 변경
				if ("Enter".equals(list.get(i).what)) {
					String msg = list.get(i).message;
					String beforename = list.get(i).name;
					String newname = map.get(list.get(i).id);
					msg = msg.replace(beforename, newname);
					list.get(i).set(newname, msg);
				}
				// 퇴장시 저장한 문자열에 닉네임 정보 추가
				else if ("Leave".equals(list.get(i).what)) {
					String msg = list.get(i).message;
					String newname = map.get(list.get(i).id);
					msg = newname + msg;
					list.get(i).set(newname, msg);
				}
			}
		}
		answer = new String[list.size()];
		// 문자열 정보 출력
		for (int i = 0; i < list.size(); i++) {
			answer[i] = list.get(i).message;
		}
		return answer;
	}
}

수정 코드 리뷰

: 위에서의 효율성을 고려하여 ID의 NAME을 저장하는 해시맵 변수를 생성하였다. 처음 for문을 통하여 record의 개수만큼 저장 하되, 해시맵 변수 key : id의 value : name을 변경 및 저장하도록 하였다. 그 후 수정을 위한 for문을 한번 더 돌려 총 2번의 for문으로 풀게 되었다. 중복된 컬럼의 정보가 바뀔 경우 해시맵을 이용하도록 하자.

 

주요 핵심 포인트

1. User 구조체 클래스를 생성하여 아이디,닉네임, 메세지, 입장or출력 변수를 만들었다.

2. User클래스 정보를 가지는 List를 선언하였다.

3. 변경 된 닉네임 정보가 있을시 HashMap 변수를 사용하여 닉네임을 변경하였다.

 

개선해야할 사항

1.  record의 개수를 고려하지 않고 풀게 되어 실패를 하게 되었다. 문제의 조건을 잘 파악하여 input 카운트가 클 경우 , for문을 최대한 중첩시키지 않고 푸는 연습을 해야할듯 하다.

'프로그래머스(JAVA)' 카테고리의 다른 글

짝지어 제거하기  (0) 2022.07.05
기능개발  (0) 2022.07.05
없는 숫자 더하기  (0) 2022.05.23
음양 더하기  (0) 2022.05.23
내적  (0) 2022.05.23

+ Recent posts