[커뮤러닝/1기] 1주차A - 그리디(Greedy)

이나영·2021년 10월 28일
0

커뮤러닝1기

목록 보기
2/8
post-thumbnail

🎯1주차A "기지국 설치"

문제설명

N개의 아파트가 일렬로 쭉 늘어서 있습니다. 이 중에서 일부 아파트 옥상에는 4g 기지국이 설치되어 있습니다. 기술이 발전해 5g 수요가 높아져 4g 기지국을 5g 기지국으로 바꾸려 합니다. 그런데 5g 기지국은 4g 기지국보다 전달 범위가 좁아, 4g 기지국을 5g 기지국으로 바꾸면 어떤 아파트에는 전파가 도달하지 않습니다.

예를 들어 11개의 아파트가 쭉 늘어서 있고, [4, 11] 번째 아파트 옥상에는 4g 기지국이 설치되어 있습니다. 만약 이 4g 기지국이 전파 도달 거리가 1인 5g 기지국으로 바뀔 경우 모든 아파트에 전파를 전달할 수 없습니다. (전파의 도달 거리가 W일 땐, 기지국이 설치된 아파트를 기준으로 전파를 양쪽으로 W만큼 전달할 수 있습니다.)

  • 초기에, 1, 2, 6, 7, 8, 9번째 아파트에는 전파가 전달되지 않습니다.

  • 1, 7, 9번째 아파트 옥상에 기지국을 설치할 경우, 모든 아파트에 전파를 전달할 수 있습니다.

  • 3개의 아파트보다 더 많은 아파트 옥상에 기지국을 설치할 경우에도 모든 아파트에 전파를 전달할 수 있습니다.

이때, 우리는 기지국을 최소로 설치하면서 모든 아파트에 전파를 전달하려고 합니다. 위의 예시에선 최소 3개의 아파트 옥상에 기지국을 설치해야 모든 아파트에 전파를 전달할 수 있습니다.

아파트의 개수 N, 현재 기지국이 설치된 아파트의 번호가 담긴 1차원 배열 stations, 전파의 도달 거리 W가 매개변수로 주어질 때, 모든 아파트에 전파를 전달하기 위해 증설해야 할 기지국 개수의 최솟값을 리턴하는 solution 함수를 완성해주세요.

제한사항

  • N: 200,000,000 이하의 자연수
  • stations의 크기: 10,000 이하의 자연수
  • stations는 오름차순으로 정렬되어 있고, 배열에 담긴 수는 N보다 같거나 작은 자연수입니다.
  • W: 10,000 이하의 자연수

입출력 예

NstationsWanswer
11[4, 11]13
16[9]23

입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다

입출력 예 #2

  • 초기에, 1~6, 12~16번째 아파트에는 전파가 전달되지 않습니다.

  • 3, 6, 14번째 아파트 옥상에 기지국을 설치할 경우 모든 아파트에 전파를 전달할 수 있습니다.


❌처음 시도했을 때 전파가 도달하는 모든 아파트를 체크하고 도달하지 않는 아파트를 다시 돌면서 최소한으로 기지국을 세우는 방법으로 코드를 작성했는데 효율성 테스트에서 전부 통과하지 못했다.

그래서 전파가 도달하는 아파트를 제외하고 돌아야 하나? 했지만 중간에 기지국이 겹치는 경우도 생각해야하기 때문에 틀린 생각이었고, 결국 시간안에 효율성 테스트는 통과하지 못했다.😥

✍🏻첫 번째 시도

class Solution {

    static boolean[] apt;

    public int solution(int n, int[] stations, int w) {
        int answer = 0;

        apt = new boolean[n+1];
        for(int i=0; i<stations.length; i++) { // 전파가 도달하는 아파트
            for(int j=0; j<w*2+1; j++) {
                if(stations[i] - w + j >= 0 && stations[i] - w + j < n+1) { // 아파트 범위 안에서
                    apt[stations[i] - w + j] = true;
                }
            }
        }

        for(int i=1; i<apt.length; i++) {
            if(!apt[i]) {
                location(i, w, n);
                answer += 1;
                i += (2 * w);
            }
        }
        return answer;
    }

    // 기지국 설치
    public static void location(int station, int w, int n) {
        for(int i=0; i<w*2+1; i++) {
            if(station + i < n+1) {
                apt[station + i] = true;
            }
            else {
                return;
            }
        }
    }
}



✔️강의를 듣고 강사님이 효율성을 높일 수 있는 세가지 팁을 말해주셨다.

💡 Tip. 효율성 높이기
1. Loop 개선
2. 적절한 데이터 구조 사용
3. 불필요한 오브젝트 제거


나는 이중for문을 사용하여 문제를 접근했기 때문에, 1. Loop를 개선하고, 3. 불필요한 오브젝트를 제거하면 효율성이 좋아질 수 있는 문제였다.

강사님은 큐를 이용해서 푸셨기 때문에 object타입(큐)보다 primitive타입을 사용하는 것이 더 효율적이라고 하셨다.

✍🏻두 번째 시도

class Solution {
    public int solution(int n, int[] stations, int w) {
        int answer = 0;
        
        // 기지국이 설치되어 있을 때 // 효율성 테스트에서 시간초과
//        Queue<Integer> sq = new LinkedList<Integer>();
//        for(int s : stations) sq.offer(s);
        
        // 큐를 사용하는 것보다 인덱스를 활용하는 것이 더 효율적이다. (object타입(큐)보다 primitive타입을 사용하는 것이 더 효율적)
        int idx = 0;

        int position = 1;
        // Loop는 더 줄일 수 없음.
        while(position <= n) {
        	if(idx < stations.length && stations[idx] - w <= position) {
        		position = stations[idx] + w + 1;
        		idx += 1;
        	}
        	else {
        		answer += 1;
        		position += w * 2 + 1;
        	}
        }

        return answer;
    }
}

profile
소통하는 백엔드 개발자로 성장하기

0개의 댓글