새소식

항해 99 TIL

99클럽 코테 스터디 7일차 TIL [Stack]

  • -

- 오늘의 학습 키워드 : Stack 활용

[문제 이름 : 과제 진행하기]

문제 url : https://school.programmers.co.kr/learn/courses/30/lessons/176962

내가 작성한 코드는 아래와 같다.

import java.util.*;

class Solution {
    public String[] solution(String[][] plans) {
        // 제일 먼저 시작하는 plans를 얻기 위해 정렬
        Arrays.sort(plans, Comparator.comparing(a -> a[1]));

        // 완료된 과제
        List<String> completedSubjects = new ArrayList<>();
        // 진행중 과제 or 멈춘 과제
        // 최근에 멈춘 과제부터 처리해야 하기 때문에 Stack 사용
        Stack<Subject> pausedSubjects = new Stack<>();

        // 첫번째 과제 시작
        int curTime = calMinute(plans[0][1]);
        pausedSubjects.push(new Subject(plans[0][0], curTime, Integer.parseInt(plans[0][2])));

        for(int i=1; i<plans.length; i++) {
            int nextTime = calMinute(plans[i][1]);
            // 진행중 or 중지된 과제가 있으면서, 현재 시작 시간이 다음 과제 시작 시간보다 앞설 때
            while(!pausedSubjects.isEmpty() && curTime < nextTime) {
                Subject curSubject = pausedSubjects.pop();
                int remainTime = nextTime - curTime;

                // 현재 과제를 마무리할 수 있는 경우
                if (remainTime >= curSubject.remainTime) {
                    // 현재 과제를 끝내고 시간 갱신
                    curTime += curSubject.remainTime;
                    // 완료된 과제 추가
                    completedSubjects.add(curSubject.name);
                } else {
                    // 남은 시간 내에 과제를 끝낼 수 없는 경우
                    // 현재 과제 남은 시간 갱신
                    curSubject.remainTime -= remainTime;
                    // 다시 스택에 추가
                    pausedSubjects.push(curSubject);
                    break;
                }
            }
            // 현재 시간을 다음 과제 시작 시간으로 업데이트
            curTime = nextTime;
            // 새로운 과제 stack에 추가
            pausedSubjects.push(new Subject(plans[i][0], nextTime, Integer.parseInt(plans[i][2])));
        }

        // 남아 있는 과제 처리
        while (!pausedSubjects.isEmpty()) {
            completedSubjects.add(pausedSubjects.pop().name);
        }

        return completedSubjects.toArray(new String[0]);
    }

    // 분 단위로 시간 게산
    static int calMinute(String time) {
        String[] times = time.split(":");
        return Integer.parseInt(times[0]) * 60 + Integer.parseInt(times[1]);
    }

    static class Subject {
        String name;
        int startTime;
        int remainTime;

        public Subject(String name, int startTime, int remainTime) {
            this.name = name;
            this.startTime = startTime;
            this.remainTime = remainTime;
        }
    }
}

 

순서는 아래와 같다.

1. 시작 시간 순으로 정렬하기 위해, Arrays.sort 메서드를 이용하여 plans 배열을 정렬한다.

2. 과제 이름, 시작 시간, 남은 시간을 저장하는 Subject 클래스를 생성한다.

3. 완료된 과제를 저장할 리스트를 선언하고, 진행중이거나 멈춘 과제를 저장할 Stack을 선언해준다.

4. 과제 개수대로 순회하며 과제 마무리 가능 여부에 따라 작업한다.

5. for문의 마지막에서 새로운 과제를 추가해준다.

6. 남아 있는 과제가 있으면, 제일 최근에 멈춘 과제부터 결과 리스트에 추가해준다.

7. 리스트를 배열로 변형하여 리턴한다.

 

위 문제에서 헷갈렸던 조건이 있었다.

'진행중이던 과제를 끝냈을 때, 잠시 멈춘 과제가 있다면, 멈춰둔 과제를 이어서 진행합니다.
만약, 과제를 끝낸 시각에 새로 시작해야 되는 과제와 잠시 멈춰둔 과제가 모두 있다면, 새로 시작해야 하는 과제부터 진행합니다.'

이를 위해 위 코드에서 for문 마지막에 새로운 과제를 우선하여 추가해주었다. 이 부분에서 시간을 많이 잡아먹은 것 같다.

 

 풀이 시간 : 55분

 

위 코드 작성 도중, 머리에 잘 떠오르지 않았던 코드들은 아래와 같다. 이에 대해 추가 개념 정리가 필요해 보인다.

1. 배열 정렬 시

Arrays.sort(plans, Comparator.comparing(a -> a[1]));

2. List -> Array로 변환

return completedSubjects.toArray(new String[0]);

 

내일은 하반기 자소서 작성을 위한 기업 분석을 할 예정이다.

 

 
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.