카테고리 없음

프로그래머스 레벨2 스택/큐 - 기능개발

JUNGKEUNG 2024. 7. 11. 21:24
반응형

 

풀이 과정

처음에는 같은 개수를 배열에 담는 문제인가? 라고 생각했다. 

 

progresses 는 각 기능의 현재 개발 진도를 나타내는 정수 배열 [ 93, 30, 55] 

speeds 는 각 기능의 개발 속도를 나타내는 정수 배열 [1, 30, 5]

 

각 기능은 개발 진도 100%일 때 서비스에 반영될 수 있다. 만약 진도가 93% 이고 속도가 1%인 기능은 7일이 걸리고, 진도가 30%인 기능은 3일이 걸린다.

 

그렇다면 어떻게 풀어야할까?

 

1. 각 직업의 남은 일수를 계산한다.

2. 남은 일수들을 순서대로 큐에 저장한다.

3. 큐에서 남은 일수를 하나씩 꺼내어 각 배포마다 몇 개의 기능이 배포되는지 계산한다.

import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        Queue<Integer> q = new LinkedList();
        for(int i=0; i<progresses.length; i++){
            int rest = 100 - progresses[i];
            if(rest%speeds[i] == 0)
                q.offer(rest/speeds[i]);
            else
                q.offer(rest/speeds[i]+1);
        }
        
        List<Integer> processList = new ArrayList();
        int process = q.peek(), cnt = 0;
        while(!q.isEmpty()){
            int n = q.poll();
            if(process < n){
                processList.add(cnt);
                cnt = 0; process = n;
            }
            cnt+=1;
        }
        processList.add(cnt);
        
        return processList.stream().mapToInt(i -> i).toArray();
    }
}

 

 

코드 풀이

Queue<Integer> q = new LinkedList();
for(int i = 0; i < progresses.length; i++){
    int rest = 100 - progresses[i];
    if(rest % speeds[i] == 0)
        q.offer(rest / speeds[i]);
    else
        q.offer(rest / speeds[i] + 1);
}
  • Quere 에는 남은 작업일을 저장할 큐를 생성해준다.
  • for 문을 통해 각 작업의 남은 진행도를 계산하여 작업 속도로 나눠 완료까지 남은 날짜를 큐에 저장해준다.
  • rest % speeds[i] == 0이면 rest / speeds[i] 값을 큐에 추가하고, 그렇지 않으면 rest / speeds[i] + 1 값을 큐에 추가한다.

 

List<Integer> processList = new ArrayList();
int process = q.peek(), cnt = 0;
while(!q.isEmpty()){
    int n = q.poll();
    if(process < n){
        processList.add(cnt);
        cnt = 0; process = n;
    }
    cnt += 1;
}
processList.add(cnt);

 

  • List<Integer> processList = new ArrayList();  각 배포마다 배포되는 작업 수를 저장할 리스트를 생성한다.
  • int process = q.peek(), cnt = 0;: 첫 번째 작업의 남은 날짜를 process 변수에 저장하고, 배포되는 작업 수를 세기 위한 cnt 변수를 0으로 초기화 한다.
  • while(!q.isEmpty()) 루프를 통해 큐에서 작업을 하나씩 꺼내어 현재 작업일(process)보다 크면 새 배포가 필요하다고 판단하여 cnt 값을 processList에 추가합니다. 이후 cnt를 초기화하고 process를 갱신한다.
  • cnt 값을 1씩 증가시켜 배포되는 작업 수를 세어준다.
  • 큐가 비어있으면 마지막 cnt 값을 processList에 추가한다.

 

    // 스트림과 람다를 사용하지 않고 List<Integer>를 int[]로 변환하는 부분
        int[] resultArray = new int[processList.size()];
        for (int i = 0; i < processList.size(); i++) {
            resultArray[i] = processList.get(i);
        }

        return resultArray;
        
        
   // 스트림, 람다 사용
   processList.stream().mapToInt(i -> i).toArray();

 

  • 마지막으로 return할때 남을 일자를 int형으로 전환하는데 코드가 지져분해져서 스트림과 람다를 이용해서 마무리를 해보았다. 

 

다른 사람 코드

import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        Queue<Integer> q = new LinkedList<>();
        List<Integer> answerList = new ArrayList<>();

        for (int i = 0; i < speeds.length; i++) {
            double remain = (100 - progresses[i]) / (double) speeds[i];
            int date = (int) Math.ceil(remain);

            if (!q.isEmpty() && q.peek() < date) {
                answerList.add(q.size());
                q.clear();
            }

            q.offer(date);
        }

        answerList.add(q.size());

        int[] answer = new int[answerList.size()];

        for (int i = 0; i < answer.length; i++) {
            answer[i] = answerList.get(i);
        }

        return answer;
    }
}

 

 

 

정리

이번 문제에서 중요하게 봐야할께 무엇일까? 간단하게 생각하면 완료까지 걸리는 일수를 정확하게 계산하는게 중요하다. 

(남은 진도/ 속도) 로 남은 일을 구할 수 있지만, 나머지가 발생하면 하루 더 필요하기 때문에 (남은 진도 + 속도 - 1) /속도 를 사용해야한다.  큐를 이용하여 작업의 완료 일수를 순서대로 처리하기 위해 큐를 이용하고 각 배포마다 몇 개의 기능이 배포되는지를 배열로 반환해야한다. 그래야 정확히 계산이 가능하다.