목차
문제
5904번: Moo 게임
Moo는 술자리에서 즐겁게 할 수 있는 게임이다. 이 게임은 Moo수열을 각 사람이 하나씩 순서대로 외치면 되는 게임이다. Moo 수열은 길이가 무한대이며, 다음과 같이 생겼다. m o o m o o o m o o m o o o o m o o m o o o m o o m o o o o o Moo 수열은 다음과 같은 방법으로 재귀적으로 만들 수 있다.


코드
코드 보기
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main { static int N; static int[] S; static boolean binarySearch(int offset, int index) { int mid = offset + S[index-1] + (index + 2); if(N <= offset + S[index-1]) { return binarySearch(offset,index-1); } else if(N <= mid) { return N == mid - (index + 1); } else { return binarySearch(mid, index-1); } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); N = Integer.parseInt(br.readLine()); S = new int[50]; int index = 0; while(N>S[index]) { index++; S[index] = S[index-1] * 2 + (index + 2); } if(binarySearch(0,index)) System.out.println("m"); else System.out.println("o"); } }
해설
문제의 N의 범위가
1 ≤ N ≤ 10^9 이므로 O(N) 으로는 풀 수 없고
이분탐색을 이용하여 풀었다
1. 점화식을 통해 N번째 글자가 나오기 시작하는 S(k) 구하기
- 코드
S = new int[50]; int index = 0; while(N>S[index]) { index++; S[index] = S[index-1] * 2 + (index + 2); }
- 코드
2. 이분탐색으로 통해 N번째 위치에 있는 글자 구하기
- 코드
static boolean binarySearch(int offset, int index) { int mid = offset + S[index-1] + (index + 2); if(N <= offset + S[index-1]) { return binarySearch(offset,index-1); } else if(N <= mid) { return N == mid - (index + 1); } else { return binarySearch(mid, index-1); } }
앞서 N번째 글자가 나오기 시작하는 index를 구했고 그 index를 가지고
binarySearch(0,index)
위와 같이 main 함수에서 재귀함수를 호출했다
재귀함수에는 이분탐색을 위해
현재 탐색하고 있는 수열의 index와
현재 탐색의 offset(시작위치)을 매개변수로 받고 있다
💡이분탐색을 사용할 때 보통 재귀함수를 사용하여 구현하는 게 개인적으로 보기도 쉽고 구현도 잘된다수열의 구분
문제에서 알 수 있듯이
수열 규칙상
수열을 앞부분, 중간부분, 뒷부분으로 구분 지을 수 있고
여기서 핵심은
중간부분은 index가 몇이 되든
"mooo..." 와 같이 맨 처음만 m이고 나머지는 o라는 사실이다
따라서,
else if(N <= mid) { return N == mid - (index + 1);
N이 맨 처음이면 return true → main함수에서 "m" 출력
아니면 return false → main함수에서 → "o" 출력
하여 N번째 글자를 출력했다
💡그 외에 앞부분과 뒷부분은 S[index-1]의 길이이므로 index를 하나씩 줄여 다시 탐색하고 있고 - 앞부분은 offset을 그대로 - 뒷부분은 offset을 mid로 바꿔 N이 중간부분에 위치할 때까지 탐색을 하는 것을 볼 수 있다- 코드
'알고리즘' 카테고리의 다른 글
[LeetCode] 104. Maximum Depth of Binary Tree (golang) (0) | 2021.06.07 |
---|---|
[LeetCode] 66. Plus One (golang) (0) | 2021.06.02 |
[LeetCode] 205. Isomorphic Strings (golang) (0) | 2021.06.02 |
[LeetCode] 455. Assign Cookies (golang) (0) | 2021.06.01 |
[LeetCode] 572. Subtree of Another Tree (golang) (0) | 2021.06.01 |
댓글