숫자 비교하기
두 수를 비교해서 다른 값을 return하는 간단한 문제다.
제한사항 조건식은 여기까지만 쓰고 이제 그만 쓰기로 했다. 코드만 길어지고 의미가 없어 보인다.
다른 사람들의 풀이를 보니 이상한 식이 나온다. 내가 이런 것을 공부했었나 싶어 다시 찾아보니 있었다.... 분명 예제 코드까지 작성했었는데 삼항 연산자의 존재조차 잊고 있었다. 반성해야겠다. if 조건문을 사용하는 것보다 간결하다. 이제 꼭 기억해 둬야겠다.
분수의 덧셈
오늘 가장 어려웠던 문제이자 나를 깊은 고통에 빠뜨렸던 문제다.
내가 생각했던 solution은
1. 분모끼리 곱한다.
2. 각 분자는 다른 쪽 분모와 곱한다.
3. 분자끼리 더한다.
4. for문을 이용해 1부터 1000까지 늘려가면서 빠짐없이 약분한다.
즉, 통분해서 더하고 약분하는 방법이었다.
테스트를 가볍게 통과하고 금방 성공한 줄 알았으나...
제출 과정에서 두 개가 다르게 나오면서 문제를 틀리게 되었다. 처음 있는 일이다. 여기서부터 고통이 시작되었다.
처음엔 for 조건문의 i < 1,000 조건식이 잘못 되었다는 사실을 알게 되었다. numer과 denom 변수는 이미 서로 곱해진 수라 1,000보다 훨씬 큰 수도 가능하다. 조건식을 고쳐 보았다.
i를 분모와 분자 둘 중 작은 수와 같은 크기까지 반복하도록 설정했다. 이렇게 하면 빈틈이 없을 거라고 생각했는데 마찬가지의 결과가 나왔다.
이후 이제 하지 않기로 했던 제한사항의 조건식을 넣어보고, for 조건문을 고쳐보고, numer과 denom의 변수를 바꿔 보는 등 수많은 삽질을 했지만 결국 성공하지 못했다. 질문하기를 눌러봐도 나와 같은 코드를 구성한 사람은 없고 방식이 제각각인 상황에서 각자 테스트 성공률도 다양하다(웃프게도 내가 그나마 높은 편이다). 그래서 내 풀이의 문제점에 대한 힌트도 얻을 수가 없었다. 결국 원인을 찾지 못해 포기하고 다른 사람의 풀이를 참고하기로 했다.
???
포기를 안하기로 했다. 이렇게 페널티가 큰 줄 몰랐다. 어떻게 모은 20점인데 무려 30점을 당장 내놓으라고 한다.
30점의 대가로 내 풀이의 잘못된 부분이 어디인지 알 수 있다면 그냥 포기할 수도 있겠으나, 질문하기를 통해 추측한 바로는 성공한 solution 중 나와 같은 logic을 사용한 solution을 찾기는 어려울 것 같았다.
그렇게 다시 고민을 거듭한 끝에 결국 원인을 알아내게 되었다. 나는 거듭제곱을 고려하지 못했던 것이다. 예를 들어 24 / 20 이라면 2^3 * 3 / 2^2 * 5 이므로, 먼저 2로 약분했으면 다시 2로 약분해야 기약분수가 된다. 그런데 내 반복문에서는 2로 약분해 12 / 10 이 된 후에 다시 2로 약분할 방법이 없다. i는 이미 2를 지나와 더 큰 수가 되었기 때문이다. 따라서 이런 상황을 피하려면 i를 999 * 999인 998,001 에서부터 내려오며 약분해야 한다. 이 정도 case를 고려 못 했다는 것은 참 한심하기 짝이 없는데, 그래도 이걸 생각해 냈을 당시에는 감격 그 자체였다.
눈물이 앞을 가린다. Lv.0에서부터 이런데 Lv.1은 대체 어떻게 푸나 싶다.
다른 사람들의 풀이는 솔직히 무슨 logic으로 푼 건지 모르겠다. 지금은 머리가 아프니 다음에 찬찬히 살펴 봐야겠다.
역시 예상대로 이 문제는 정답률 낮은 순에서 상위권에 위치해 있다. 복병이 무려 7번째 문제에 숨어 있을 줄은 몰랐다. 그러나 이 정도 문제도 못 푸는 실력으로 Lv.1 문제는 손조차 댈 수 없을 것이다. 마침 코딩테스트 책도 주문해 두었으니 열심히 공부해 봐야겠다.
배열 두 배 만들기
문제에 주어진 answer을 이용하려 한다면 number 배열의 내용을 answer에 옮겨야 한다.
answer 배열을 numbers 배열과 같은 길이로 선언한 뒤 그대로 복사했다. 이 과정에서 새로운 배열에 복사하는 과정이 잘 기억이 안 나 책을 뒤지게 되었다. 다시 공부해야겠다.
이렇게 그냥 numbers 변수로 답까지 내면 당연히 쉽고 간결하다. 그런데 문제에서 answer가 주어졌는데 이렇게 풀어도 되는 것일까? answrt는 그냥 샘플 정도인 걸까? 모르겠다. 공부를 더 하다 보면 알게 될 것이다.
나머지 구하기
아주 쉬운 문제다. num1을 num2로 나눈 나머지를 구하면 된다.
이 풀이는 참신한 방법으로 풀었다. 나누는 대신 뺄셈을 계속 반복해 나머지를 구했다. 원시적인 나눗셈인 셈이다. %가 생각이 안 났나 보다.
중앙값 구하기
두 번째 문제처럼 고민을 아주 많이 했던 문제다. 크기 순으로 정렬하는 method가 있을 것은 분명한데, 문제는 내가 그 method를 아직 모른다는 것이다. 아무래도 Java 공부를 더 많이 하고 코딩테스트를 풀어야 될 것 같다.
한참을 고민한 후에 내가 생각해 낸 방법은
1. for j 반복문을 통해 array 배열의 최대값을 max에 대입한다.
2. for k 반복문을 통해 해당 최대값을 가지는 항목을 다시 찾아 -1,000으로 바꾼다.
3. 같은 크기의 다른 항목이 더 있다면 또 찾아 바꾸지 않도록 break로 for k 반복문을 끝낸다.
4. for i 반복문을 통해 1~3의 과정을 array.length / 2 번만큼 반복한다. 이 과정에서 중앙값보다 큰 수들이 전부 -1,000이 된다.
5. answer에 array 배열의 최대값이자 원래는 중앙값이었을 놈을 대입한다.
결국 코드가 조잡하고 복잡해졌다. 이 과정에서 실수도 많이 했는데, answer와 max의 초기값을 습관적으로 0으로 선언한 것과, 이 구조의 핵심이 되는 max 변수가 최대값이 된 상태에서 다시 줄여주는 작업을 하지 않은 것이다.
answer와 max의 초기값을 -1,000으로 선언하고 max를 for i 반복문의 첫 줄에서 다시 -1,000으로 만들어 주었다. 일단 작동은 한다.
그래... 내가 이걸 몰라서 이 개고생을 했다. 그래도 처음에는 아예 감이 안 잡혔었는데, 조잡하게나마 방법을 떠올린 것 자체가 기적이다. 앞으로 Java 진도를 더 빠르게 나가야겠다.
'Coding Test' 카테고리의 다른 글
Java 코딩테스트 연습 5일차(2) (프로그래머스 스쿨 Lv.0, 1061점) (2) | 2023.03.11 |
---|---|
Java 코딩테스트 연습 5일차(1) (프로그래머스 스쿨 Lv.0, 1055점) (0) | 2023.03.11 |
Java 코딩테스트 책 구입, 연습 4일차 (프로그래머스 스쿨 Lv.0, 1045점) (0) | 2023.03.10 |
Java 코딩테스트 연습 2일차 (프로그래머스 스쿨 Lv.0, 1019점) (0) | 2023.03.08 |
Java 코딩테스트 연습 1일차 (프로그래머스 스쿨 Lv.0, 1013점) (0) | 2023.03.07 |