TIL (Today I Learned)

99클럽 코테 스터디 8일차 TIL + 오늘의 학습 키워드

남 희 2024. 7. 29. 23:16

☑️ 문제: 기능개발

https://school.programmers.co.kr/learn/courses/30/lessons/42586

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

☑️ 처음 풀었을 때 코드

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        int N = progresses.length;
        int front = 0; // progresses를 Queue처럼 쓸 예정
        
        int step = 0;
        int[] deploy = new int[N];
        while (front < N) { // 모두 꺼낼 때까지
            // 1. 현재 가리키는 것의 작업이 끝났는지 확인한다.
            if (progresses[front] < 100) {
                for (int i = 0; i < N; i++) {
                    progresses[i] += speeds[i];
                }
                continue;
            }
            
            // 2. 작업 끝났다면, 작업이 끝난 모든 기능을 배포한다.
            while (front < N && progresses[front] >= 100) {
                deploy[step]++;                
                front++;
            }
            step++;
        }
        
        int[] answer = new int[step];
        for (int i = 0; i < step; i++) {
            answer[i] = deploy[i];
        }
        
        return answer;
    }
}

 

하지만, 시간과 메모리가 균일하지 못하고, 오래걸린다.

왜냐하면 for문으로 progresses[i] += speeds[i]을 실행시킬 때, N의 크기가 커질수록, progreeses와 speedes의 크기가 작을수록 속도에서 불리하기 때문이다.

더보기

당시 문제 이해 과정

 

// 기능은 진도가 100%일 때 서비스에 반영할 수 있다.
// 기능의 개발속도는 모두 다르기 때문에
// 뒤에 잇는 기능이 앞에 있는 기능보다 먼저 개발될 수 있다.
// 그럴 수는 있지만,
// 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다. -> 즉, 앞에 거가 다 되어야 빼낼 수 있다는 뜻. (Queue)

// Answer : 각 배포마다 몇 개의 기능이 배포되는가?
//  -> 배포 횟수를 알아야 하고, 각 배포 때 몇 개의 기능이 배포되는지 알아야 한다.

//  ("Answer"은 소요 날짜 기준이 아닌 각 배포일 기준임을 기억하자.)

 

☑️ 페어프로그래밍 코드

import java.util.*;

class Solution {
    public static ArrayList<Integer> solution(int[] progresses, int[] speeds) {
        ArrayList<Integer> answer = new ArrayList<>();

        int maxValue = getLeft(progresses, speeds, 0);
        int tmp = 1;
        for (int i = 1; i < speeds.length; i++) {
            int left = getLeft(progresses, speeds, i);

            if (maxValue < left) {
                answer.add(tmp);
                tmp = 1;
                maxValue = left;
                continue;
            }
            tmp++;
        }
        answer.add(tmp);

        return answer;
    }

    private static int getLeft(int[] progresses, int[] speeds, int i) {
        int leftProgress = 100 - progresses[i];
        return leftProgress % speeds[i] > 0 ? (int)(leftProgress / speeds[i]) + 1 : (int)(leftProgress / speeds[i]);
    }
}

페어께서 (100 - progresses) / speeds를 사용해 풀이한 코드가 인상깊었다!

이렇게 하면 긴 탐색을 할 필요가 없다.

그저 남은 일수, 그리고 처음 큰 수와 그 다음 큰 수 사이의 숫자의 개수만 있다면 풀 수 있다!

이렇게 하니, 시간과 메모리 모두 짧게 나왔다!

 

☑️ 복습 - deep link

Deep Link 방법은 여러 가지가 있는데, URL scheme은 Android, iOS모두 사용할 수 있다.

하지만 주의할 점, URL scheme은 보안에 취약하다.

https://hagsig.tistory.com/241 -> 이 블로그 글을 읽으면 얼마나 취약한지 알 수 있다.

scheme은 plist로 쉽게 알 수 있고, path도 쉽게 유추 가능한 코드 위치와 형식이 존재하며, 인자로 넣더라도 예상할 수 있다.