Post

[프로그래머스/LV3] 기지국 설치 - 수학(Java)

프로그래머스 LV3 기지국 설치 문제를 Java로 해결한 풀이입니다. 구간을 활용하여 길이가 1일때, 길이가 2이상일때 경우를 나누어 문제 푸는 방법을 설명합니다.

[Summer/Winter Coding(~2018)] 기지국 설치

🙋‍♂️ 들어가며

이 문제는 1 <= stations.length <= 10000

n <= 2억 이라서 구간, 그리디로 풀면 좋겠다는 생각이 들었다

그리고 문제의 구간범위인 2w+1 을 활용할 수 있을 것 같았다

stations이 1개일 때

stations이 2개 이상일 때

각각 나누어 보면 다음과 같다

testcase-1

1
2
3
4
n = 16
stations = [9]
w = 2
answer = 3

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

이렇게되면 (7~11) 제외하고 (1,6) 그리고 (12, 16)이 필요하다

길이가 1일때는 구간을 중심으로 왼쪽, 오른쪽 계산처리를 해주면 되겠다



testcase - 2

1
2
3
4
n = 29
stations = [2, 9, 23]
w = 2
answer = 4

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

이러면 빈구간 (5,6), (12, 20), (26, 29)가 나오게 된다

위 테스트케이스 2개를 보고 든 생각은 빈구간을 커버하기 위해, 첫 시작점(start)을 1로 설정하고, 현재 구간 시작점 - 기존 시작점 >= 1 일때만 계산을 한다.

첫 시작점인 start를 구간마다 갱신을 하는데 물론 길이가 2이상일때만 적용된다

그리고 길이가 2이상이고 마지막 인덱스일때 끝구간도 계산하면된다




✅ 코드 O(N)

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Solution {
    public int solution(int n, int[] stations, int w) {
        
        
        // int n1 = 29;
        // int[] stations1 = new int[] {2, 9, 23};
        // int w1 = 2;
        // res -> 4
        
        
        int res = my_inspector(n, stations, w);
        return res;
    }
    
    
    static int my_inspector(int n, int[] stations, int w) {
        int cnt = 0;
        
        // 예외처리 (stations 길이가 1일때)
        if (stations.length == 1) {
            int idx = 0;
            int start = 1;
            int end = n;
            int s = stations[idx] - w;
            int e = stations[idx] + w;
            
            // 앞구간 처리 (기지국 설치할 곳이 있다면)
            if (s - start >= 1) {
                System.out.println(s-start);
                cnt += (int) (Math.ceil( (double) (s-start) / ((2*w)+1)) );
            }
            
            // 뒷구간 처리 (기지국 설치할 곳이 있다면)
            if (end - e >= 1) {
                cnt += (int) (Math.ceil( (double) (end-e) / ((2*w)+1) ));
            }
            return cnt;
        }
        
        
        // stations.length >= 2 일때
        
        // 0. 구간을 갱신할 첫 시작점
        int start = 1;
        int N = stations.length;
        for (int i = 0; i < N; i++) {
            int s = stations[i] - w;
            int e = stations[i] + w;
            
            // 1. idx 맨처음
            if (i == 0) {
                // 1-1. 길이가 1이상일때만 계산
                if (s - start >= 1) {
                    cnt += (int) (Math.ceil( (double) (s-start) / ((2*w)+1)) );
                }
                // 1-2. 다음 시작점을 갱신
                start = e+1;
            }
            // 2. idx 맨끝
            else if (i == N-1) {
                // 2-1. 길이가 1이상일떄만 계산 (구간 다 커버 못할때)
                if (s - start >= 1) {
                    cnt += (int) (Math.ceil( (double) (s-start) / ((2*w)+1) ));
                }
                // 2-2. idx가 맨끝이니 끝도 계산 (구간을 커버하지 못할때)
                if (n-(e+1) >= 1) {
                    cnt += (int) (Math.ceil( (double) (n-e) / ((2*w)+1) ));
                }
            }
            
            // 3. idx 맨처음과 맨끝사이
            else {
                // 3-1. 길이가 1이상일떄 (구간 다 커버못할때)
                if (s - start >= 1) {
                    cnt += (int) (Math.ceil( (double) (s-start) / ((2*w)+1) ));
                }
                // 3-2. 다음 시작점 갱신
                start = e + 1;
            }
        }
        
        // 4. 횟수 반환
        return cnt;
    }
}
This post is licensed under CC BY 4.0 by the author.

Trending Tags

반갑습니다 무엇을 도와드릴까요?