프로그래머스 연습문제
프로그래머스 - 가운데 글자 가져오기
단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요.
단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.
s는 길이가 1 이상, 100이하인 스트링입니다.
public static String solution(String s) {
String answer = "";
int len = s.length();
if(len % 2 == 0){
answer = s.substring(len-(len/2)-1, len-(len/2) + 1);
} else {
answer = Character.toString(s.charAt(len / 2));
}
return answer;
}
처음 코드는
홀수일 때와 짝수일 때를 조건문으로 나누고,
짝수일 경우 두 문자를 가져와야 해서 substring
홀수일 경우 한 문자를 가져와야 해서 charAt을 사용했다.
문제없이 통과하긴 했지만 개선의 여지가 다분해보여
좀 더 생각을 해보기로 했다.
public static String solution(String s) {
String answer = "";
int halfLength = s.length() / 2;
if(s.length() % 2 == 0) {
answer = s.substring(halfLength - 1, halfLength + 1);
} else {
answer = s.substring(halfLength, halfLength + 1);
}
return answer;
}
1번 코드에서 고민하다가 조건문 수식의 가독성을 높이는 동시에
나눗셈 연산 횟수를 줄이기 위한 수정을 했다.
변수에 문자열의 길이가 아니라 문자열 길이 / 2 값을 저장한 뒤
해당 변수를 활용해 연산을 하니 코드의 가독성이 높아졌다.
나눗셈 연산 횟수도 세 번에서 한 번으로 줄었다.
그리고 문자열 길이가 홀수일 경우 charAt을 사용했는데
charAt을 사용할 경우 char형 문자를 문자열로 변환해야 해서
불필요하게 한 과정을 더 거쳐야 한다.
따라서 불필요한 문자열 변환을 없애기 위해
charAt을 substring으로 변경했다.
1번 코드의 경우 테스트 결과들에서 처리시간으로
0.03ms ~ 0.05ms 범위의 값들이 결과로 나왔는데,
위와 같이 수정하고 나니
처리시간이 0.01ms ~ 0.03ms로 절반정도 감소했다.
public String solution(String s) {
int len = s.length();
return s.substring((len-1) / 2, len/2 + 1);
}
2번 코딩을 결과물로 제출하고 나서 다른 사람들은 어떻게 풀었는지 살펴보다
한 코드를 보고 충격을 받았다.
그 코드는
내가 8줄정도의 코드로 해결한 문제를 단 한 줄로 해결하고 있었다.
람다, 스트림같이 어려운 기능이 아닌 substring만을 사용하면서 말이다.
문자열 길이의 홀수와 짝수에 따라 조건문으로 나눠야겠다는 나의 지레짐작은
더 간단한 길로 갈 수 있는 생각을 막아버리고 있었다.
예를 들어
문자열 길이가 4일 경우
substring의 begin값, end 값은 각각 1, 3이 되어야 한다.
문자열 길이가 5일 경우
substring의 begin값, end값은 각각 2, 3이 되어야 한다.
문자열 길이가 6일 경우
substring의 begin값, end값은 각각 2, 4이 되어야 한다.
문자열 길이가 7일 경우
substring의 begin값, end값은 각각 3, 4이 되어야 한다.
이렇게 begin값과 end값의 예시를 늘어놓고 보면 규칙성이 보이기 시작한다.
int형 기준
begin값은 (문자열길이-1) / 2
end값은 (문자열길이/2) + 1
의 공식으로 해당 문제의 규칙성을 구현해 낼 수 있다.
그리하여
return s.substring((s.length()-1) / 2, (s.length()/2) + 1);
라는 한 줄 코드만으로 문제가 해결이 된다.
가독성을 높이기 위해 나는 문자열 길이를 변수로 빼서
int len = s.length();
return s.substring((len-1) / 2, len/2 + 1);
위와 같이 작성했다.
처리시간은 0.02ms~0.03ms정도로 2번과 비슷하나
코드는 매우 깔끔해졌다.
역시 코딩의 세계는 무궁무진한 것 같다.
내가 아무리 "이정도에서 더 나아질 게 있나?" 라는 생각을 하더라도
내 생각을 가볍게 비웃듯이 "응, 이렇게 하는 방법도 있지" 하면서
감탄사가 나오게 만드는 코드들이 펑펑 튀어나온다.
이러한 코드들을 철저하게 이해하고, 내 것으로 만들어서
나도 이런 코드들을 자유자재로 짤 수 있게 되고 싶다는 생각이 들었다.
이번엔 좀 더 나은 코딩으로 갈 수 있는 가능성을
지레짐작만으로 시작부터 차단해 버린 것이 무척이나 아쉬웠다.
길이의 홀수, 짝수를 나누어 처리한다는 생각을 하기 전에
예시를 들어 begin값과 end값을 늘어놓고 확인했다면
규칙성을 직접 발견할 수 있지 않았을까 아쉬움이 남는다.
하지만 중요한 경험이였다 생각한다.
처음부터 가능성을 차단하고 코딩을 하면 어떻게 되는지 몸소 느꼈기에
다음부터는 조금 더 가능성을 열어두고,
넓은 시야에서 문제를 바라보아야 겠다는 생각이 들었다.