프로그래머스/Lv. 2

[프로그래머스 코딩테스트] 기능개발(Java)

Sigfriede 2023. 7. 15. 01:00

  문제 설명

  프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.

  또 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.

  먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

 

  제한사항

  • 작업의 개수(progresses, speeds 배열의 길이)는 100개 이하입니다.
  • 작업 진도는 100 미만의 자연수입니다.
  • 작업 속도는 100 이하의 자연수입니다.
  • 배포는 하루에 한 번만 할 수 있으며, 하루의 끝에 이루어진다고 가정합니다. 예를 들어 진도율이 95%인 작업의 개발 속도가 하루에 4%라면 배포는 2일 뒤에 이루어집니다.

 

  입출력 예

progresses speeds return
[93, 30, 55] [1, 30, 5] [2, 1]
[95, 90, 99, 99, 80, 99] [1, 1, 1, 1, 1, 1] [1, 3, 2]
import java.util.ArrayList;
class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        int[] array = new int[progresses.length];
        for (int i = 0; i < progresses.length; i++) {
            int day = 0;
            while (progresses[i] < 100) {
                progresses[i] += speeds[i];
                day++;
            }
            array[i] = day;
        }
        ArrayList<Integer> list = new ArrayList<>();
        int cur = array[0];
        int count = 1;
        for (int i = 1; i < array.length; i++) {
            if (cur >= array[i]) {
                count++;
            } else {
                list.add(count);
                cur = array[i];
                count = 1;
            }
        }
        list.add(count);
        int[] answer = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
        }
        return answer;
    }
}

  배열 array를 생성하고 크기는 progresses의 길이로 지정합니다.

  for문이 progresses의 길이만큼 순회합니다.

  변수 day를 생성합니다. 이는 작업이 며칠만에 개발되는지 세어 array에 삽입할 것입니다.

  while문이 progresses의 i 번째 원소가 100보다 작은 동안 반복합니다.

  progresses의 i 번째 원소에 speeds의 i 번째 원소를 더하기 할당합니다.

  작업이 진행되었으므로 day가 증가합니다.

  array의 i 번째 원소에 day를 할당하여 며칠 째에 작업이 완료가 되었는지 확인합니다.

  ArrayList를 생성합니다. 이는 배포마다 몇 개의 기능이 배포되는지 확인합니다.

  변수 cur를 생성하고 array의 0 번째 원소를 할당합니다. 배포는 순서대로 진행되어야 하기 때문입니다.

  변수 count를 생성합니다. 하루에 몇 개의 기능이 배포되는지 담을 변수입니다. 첫 번째 작업은 이미 배포되었다고 가정하므로 1부터 시작합니다.

  for문이 1번 인덱스부터 array의 길이만큼 순회합니다.

  if문에서 cur가 array의 i 번째 원소보다 크거나 같은지 확인합니다. 만약 array의 i 번째 원소가 더 크다면 cur의 작업이 완료된 시점에서 array의 i 번째 원소는 아직 작업이 끝나지 않았다는 것을 의미합니다. 따라서 조건에 만족한다면 count가 증가하여 배포될 기능의 수가 증가합니다.

  만약 앞선 조건에 해당하지 않는다면 add 메소드를 이용하여 list에 count를 삽입합니다.

  cur를 array의 i 번째 원소로 갱신합니다.

  count를 1로 초기화하여 다시 몇 개의 기능이 배포될 지 세기 시작합니다.

  add 메소드를 이용하여 다시 list에 count를 삽입합니다. 마지막 배포를 추가하기 위함입니다.

  다음은 list에 추가된 값을 answer 배열에 복사하는 것입니다.

  answer 배열의 크기는 list의 크기로 지정합니다.

  for문이 list의 크기만큼 순회합니다.

  answer의 i 번째 원소에 list의 i 번째 원소를 할당합니다.

 

 

  아래는 실패한 풀이(Queue)

import java.util.Queue;
import java.util.LinkedList;
import java.util.ArrayList;
class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < progresses.length; i++) {
            queue.add(progresses[i]);
        }
        ArrayList<Integer> list = new ArrayList<>();
        while (!queue.isEmpty()) {
            int size = queue.size();
            int count = 0;
            for (int i = 0; i < size; i++) {
                int progress = queue.poll() + speeds[i];
                queue.add(progress);
            }
            while (!queue.isEmpty() && queue.peek() >= 100) {
                queue.poll();
                count++;
            }
            if (count > 0) {
                list.add(count);
            }
        }
        int[] answer = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
        }
        return answer;
    }
}

  queue에 progresses의 원소를 집어넣습니다. 큐에서 원소를 하나씩 꺼내면서 꺼낸 값에 speeds를 더해줍니다. 더해준 값이 100이 될 때까지 큐의 뒷부분에 값을 추가합니다.

  테스트 케이스에 [90, 90, 90, 90], [30, 1, 1, 1], [1, 3]을 넣었을 때 실패했습니다.

  큐의 이론적인 부분은 이해한 듯하지만, 구현 경험이 적다보니 이렇게 구현하려고 하면 막막해지는 듯합니다. 조금 더 연습해야겠습니다.