문제 분석
문제 목표 : 초침이 시침/분침이 만나는 횟수 구하기
할말이 많은 문제다.
이 문제를 어떻게 접근할것인가 큰 문제다.
결론부터 말하자면, 대부분의 사람들이 이 문제를 "사고력"으로 접근하였다.
즉, 매 초 각도계산하면서 시침/분침과 겹치는지 완전탐색같은건 안돌린다는것이다.
=> 사고력으로 접근한다는것은 규칙이 있다.
하나의 예시를 줬는데 이걸 잘 이용해 먹어야한다.
간단하게 규칙을 계산해 보자.
1. 1분에 초침은 1바퀴를 돈다.
2. 1바퀴를 돌면, 일반적으로 시침과 분침을 만나게 된다.
3. 즉, 1분이 자나가면 알람이 2번은 울린다.
이 규칙대로면 1시간 = 120번, 24시간 = 2880번이다.
잃어버린 28번은 무엇인가?
이걸 잘 찾아내는것이 문제의 핵심이다.
우선 분침이 정각이 되기전 1분전 상황을 살펴보자.
EX) X시 59분 -> (X+1)시 00분
시뮬레이션을 돌려보면, 초침과 분침은 만나지않는다.
즉, 1시간 마다 1번의 알람이 생략된다.
이럼에도 불구하고 4번이 더 남는다.
이것은 초침과 시침이 정각으로 모였을때의 소실이다.
시침이 정각으로 모일때는 딱 2번 0시 0분 0초, 12시 0분 0초 2곳이다.
분침과 같은 이론으로 2번이 생략된다.
또한, 0시 0분 0초와 12시 0분 0초에는 특수한 경우가 발생되는데, 시/분/초가 모두 모인다.
문제에서 다음과 같이 모두 모이는 경우 1번으로 처리하기때문에 생략을 1번더 해줘야한다.
즉, 잃어버린 4번의 이유를 찾았다.
2880-24-4 = 2852
여기까진 좋은데, 문제는 시작시간과 도착시간이 정각이 아니다.
즉, X초 동안 몇번 울렸는지를 구해야한다.
위에서 아날로그의 규칙을 제대로 파악했다면 식을 짤수가있다.
분침이 1바퀴를 돌때를 추측해보자. 분침이 1바퀴를 도는데 1시간 =3600초가 걸린다.
1시간동안 분침과 초침은 60바퀴 초침간에는 59번 울린다. 즉, 3600/59초 마다 1번씩 울린다. (약, 60초안되는 시간같다)
시침도 마찬가지로 1바퀴를 돌때, 초침은 720바퀴 시침이 1바퀴를 도는데 12시간 = 43200초가 걸린다.
12시간동안 초침은 719바퀴를돈다. 즉, 43200/719초 마다 1번씩 울린다.
이걸 수식으로 나타내면 다음과 같다.
문제 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
class Solution {
public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
int answer = 0;
// 0초 ~ 23시 59분 59초가 2852인 이유 추측해보자
// 1분 = 2번 60분 = 120 0초~59분 59초라 가정, 119번 울림 (60분 제외)
// 118*24 = 2832
// 119*24 = 2856 4번이 생략이됨 왜일까..?
// 0시 , 12시는 시 분 초침이 모두겹침 -2 카운트
// 11시 59분 ->12시 , 23시 59분 -> 0시 초침이 만나는 일이 발생안함 -2
// 즉 , 0시 ,12시 부근에 각각 -2번 생략이된다.
//But, 이 법칙은 끝나는시각이 정각일경우만 유효하다.
int bonus=0;
//이것은 시작시간이 알람일경우 시작하자마자 알람이 울리기때문에
// +1번을 해줘야한다.
if(h1*3600+m1*60+s1==0 ||h1*3600+m1*60+s1==43200){
bonus=1;
}
return getCount(h2,m2,s2)-getCount(h1,m1,s1)+bonus;
}
//끝나는 시각은 정각이 아니다. 유동적이다.
//즉, x초동안 몇번 울리는지를 정확하게 알아야함
// 초-분 관점 60분 = 3600초 , 초침은 60바퀴 1바퀴 =1번울림
// 3600초동안 59번알람 (마지막바퀴는 안만남)
// 즉 , 3600/59초당 1번 울림
//그렇다면, x초/59를 하면 x초동안 시-분 알람을 구할수있지않나?
// 초-시 관점 시침이 0시~12시 까지 12시*3600=43200
// 43200초동안, 초침은 720바퀴
// 즉 , 43200초동안 719번 알람 (마지막 바퀴는 안만남)
// 463200/719초당 1번 울림
public int getCount(int h1,int m1, int s1){
int total = h1*3600+m1*60+s1;
int m_alram = total*59/3600;
int h_alram = total * 719/43200;
int answer = m_alram+h_alram;
if(h1>=12){
answer--;
}
return answer;
}
}
|
cs |
'알고리즘 > 프로그래머스 Level2' 카테고리의 다른 글
[PCCP 기출문제] 석유 시추 (0) | 2024.01.23 |
---|---|
[프로그래머스,java] 두 원 사이의 정수 쌍 (1) | 2023.04.18 |
[프로그래머스,Java] Level2: 과제 진행하기 (0) | 2023.04.01 |
[프로그래머스,Java] Level2: 리코쳇 로봇 (0) | 2023.03.24 |
[프로그래머스,Java] Level2: 호텔 대실 (0) | 2023.02.03 |