[TIL] 230617 (코딩테스트: 완주하지 못한 선수, 이상한 문자 만들기)

CountryGirl·2023년 6월 17일
0

TIL

목록 보기
3/80

📌 완주하지 못한 선수

문제점 & 시도 & 해결

마라톤에 참여한 선수들 중에서 완주하지 못한 선수를 찾아야하는 문제이다.
아무 생각없이 그냥 배열로 문자열만 비교해서 해결하려고 했지만,

참여한 선수들 중에 동명이인 있다는 제한사항이 있었다.
만약 단순하게 배열을 사용하여 문자열만 비교한다면, "홍길동", "홍길동" 이렇게 동명이인 중에 한 명만 완주를 할 경우 완주하지 못한 "홍길동"을 찾을 수가 없었다.. (나의 능력으로...)

participant : ["Kim", "Park", "Kim", "Lee"]
completion :["Park", "Lee", "Kim"]
answer : "Kim"

문제를 보니 "해시"로 푸는 문제였다.

하지만 나는 HashMap 을 몰랐다.
그래서 일단 내가 할 수 있는 방법으로 해보았다.

그대로 들어온 문자열 배열을 가지고는 할 수 없어서
다시 생각한 방법은
배열을 sort() 한 후, 두 배열 비교하여 같지 않은 index의 값이 완주하지 못한 선수이다.

먼저 sort() 하고

Arrays.sort(participant);
Arrays.sort(completion);

participant 의 각각 index 에 해당하는 문자열과 completion 의 각각 index 에 해당하는 문자열을 equals()로 비교하여 같지 않을 때 result 에 넣어주어주고 break 를 하였다.

for (int i = 0; i < completion.length; i++) {
	if(!participant[i].equals(completion[i])){
		answer = participant[i];
		break;
	}
}

이렇게 작성하여 채점을 해보았는데 많이 틀렸다.....

반례가 있었다.
만약

participant : ["Kim"]
completion :[]
answer : "Kim"

participant 가 1명이라면 completion 는 빈 배열이 되고 answer 은 participant 의 그 1명이 출력되어야 한다.

제가 작성한 코드는 그 1명이 출력되지 않고 빈 문자열이 출력되었다.
조건과 코드를 추가하여 빈 문자열도 처리할 수 있도록 하였다.

if(answer.equals("")) answer = participant[participant.length - 1];

원래 이 문제는 해시였지만 내가 해시를 알지 못해 sort()로 푼 문제이다.
그래서 해시를 조금 공부한 다음 문제를 다시 풀어보았다.

participant 를 key값으로 받고, value 값을 default로 0을 넣은 후, 1을 더해주었다.
completion 을 key값으로 받고, value 값을 participant value에 반대로 1을 빼주었다.

만약 동명이인 없을 경우 1에서 1을 뺏으므로 0이 나와야한다.
동명이인이 있다면 0이 아니어야한다.

나는 HashMap에 익숙하지 않아 forindex를 바로 돌릴 수 있을 줄 알았다.
index를 넣을 경우 구문오류가 떳고, 많이 당황했다.

그래서 결국 다른 사람의 풀이를 보았다......
다른 사람의 풀이에

for (String key : hashMap.keySet()) {
            if (hashMap.get(key) != 0) answer = key;
        }

라고 되어있었다.
나는 이해가 가지 않았다.

분명 value 와 0을 비교하여 0이 아닐 경우 answer 에 넣는 것인데
value가 아닌 key를 비교하고 있었다.

그래서 hashMap 을 출력해보았다.

participant = {Lee=1, Kim=2, Park=1}

key = value 로 출력이 되고 있었다.

그래서 value 가 아닌 key 를 비교해야한다는 것을 알게 되었다.


📌 이상한 문자 만들기

문제점 & 시도 & 해결

" " 공백으로 구분되는 단어들로 만들어진 문자열을 각 단어의 짝수번 째는 대문자로 홀수번 째는 소문자로 바꾸어 출력을 하는 것이었다.
" " 공백으로 구분되어 있었기 때문에 split() 으로 단어를 쪼개야겠다고 생각했다.

String[] stringArray = s.split(" ");

쪼갠 후, 각 단어들의 index를 짝수, 홀수로 나눠 toUpperCase(), toLowerCase() 를 하였다.

// for (int i = 0; i < stringArray.length; i++) 
// String word = "";
if (j % 2 == 0) word += Character.toUpperCase(stringArray[i].charAt(j));
else word += Character.toLowerCase(stringArray[i].charAt(j));

Output이 Input처럼 문자열로 나와야했고, 단어들이 " " 공백으로 나눠져야 했기때문에

// for (int i = 0; i < stringArray.length; i++) 
if (i == stringArray.length - 1) answer += word;
else answer += word + " ";

를 추가해주었다.

문자로 이루어진 일반적인 문자열이라면 문제없이 출력이 잘 되었다.
하지만 채점을 한 결과, 또 많이 틀렸다.

도저히 반례를 찾을 수 없어 다른사람들 의견을 보며 팀원들과 같이 방법을 생각해보았다...

만약 공백이 문자열이라면,
즉,

s = "try hello world"; 

처럼 일반적인 문자로 이루어진 단어들의 문자열이 아니라

s = "___ try hello ___ world _ ___"; // _ : 공백을 의미함

공백으로 단어를 이루고 있다면, 틀리는 것이었다.

반례를 넣어 다시 출력해보니

앞에 있는 공백 단어와 중간에 있는 공백 단어는 문제 없이 출력이 되었지만
뒤에 오는 공백 단어는 출력이 되지 않았다.

s = "___ try hello ___ world _ ___";
s = "ooo try hello ooo world x xxx"; 	// o: 정상적으로 출력을 의미, x: 출력되지 않음을 의미

이렇게 작동되고 있었다.

뒤에 오는 공백의 길이 만큼 그 길이만큼 다시 answer 에 붙여주기로 하였다.

우리는 answer를 출력하면 뒤에 오는 공백들은 무시하고 출력이 된다는 것을 여러 번에 코드 수정을 통해 알고있었다.
s의 길이와 answer의 길이를 빼면 무시된 공백들의 길이가 된다.

int spaceNum = s.length() - answer.length();
return answer + " ".repeat(spaceNum);

repeat()로 answer 에 붙여 return 해주었다.


알게 된 점

HashMapindex를 바로 그냥 쓸 수 없다는 점.
Map에서 value를 비교하고 싶다면 key를 비교한다는 점.
문자열 맨 뒤에 " "공백이 있으면 공백은 출력되지 않고 무시된다는 점.

을 알게 되었다.

profile
💻🌾시골소녀의 엉망징창 개발 성장일지🌾💻 (2023.05.23 ~)

0개의 댓글