https://school.programmers.co.kr/learn/courses/30/lessons/150368?language=java

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

입력

2차원 배열 users는 각 유저의 할인 기준과 구매 기준 금액
각 요소는 [할인 기준 %, 구매 기준 금액] 형식
정수 배열 emoticons는 이모티콘 정가 리스트이며, 각 이모티콘마다 10%, 20%, 30%, 40% 중 하나의 할인율을 선택 가능

 

핵심 아이디어

각 이모티콘에 대해 10%, 20%, 30%, 40% 할인율을 적용한 모든 조합을 완전탐색
각 조합마다 모든 유저가 어떻게 반응하는지를 시뮬레이션
사용자는 자신이 설정한 할인 기준 이상인 이모티콘만 구매 대상으로
총 구매 금액이 기준 금액 이상이면 이모티콘 플러스에 가입하고, 구매 X
그 외의 경우에는 구매한 이모티콘들의 금액을 모두 합산
가입자 수를 우선으로 비교하고, 같을 경우 총 판매 금액이 높은 조합을 선택

 

변수 설명

plus: 현재까지 나온 최대 플러스 가입자 수
buy: plus 기준에서의 최대 이모티콘 판매 금액
arr: 현재 할인율 조합을 저장하는 배열 (이모티콘 개수와 동일한 길이)
recursive: 가능한 모든 할인율 조합을 탐색하는 재귀 함수
calc: 현재 할인 조합에서 유저 반응을 계산하는 함수
userPer: 해당 유저가 구매를 고려하는 최소 할인율
userLimit: 해당 유저의 플러스 가입 기준 금액
sum: 유저가 실제 구매한 총 금액
cnt: 현재 조합에서 플러스 가입한 유저 수
buySum: 실제 구매가 발생한 총 금액

 

예시

- 입력
users = { {40, 10000}, {25, 10000} }
emoticons = {7000, 9000}

가능한 할인 조합은 4^2 = 16가지이다
예를 들어 할인율 조합이 [40, 40]이면
7000 * 0.6 = 4200
9000 * 0.6 = 5400
유저 1은 40% 이상만 보기 때문에 두 이모티콘 모두 구매
총합 9600 → 10000 미만 → 구매함
유저 2는 25% 이상 조건 만족, 동일하게 총합 9600 → 구매함
따라서 플러스 가입자 0명, 구매 총액 19200원
이와 같은 방식으로 모든 조합을 비교해 가장 많은 가입자 수와 가장 높은 판매금액 조합을 선택

- 출력

[최대 플러스 가입자 수, 해당 조건에서의 최대 판매 금액] 형태의 정수 배열을 반환

 

 

정답코드

import java.util.*;

class Solution {
    private int plus = 0;
    private int buy = 0;

    public int[] solution(int[][] users, int[] emoticons) {


        int[] arr = new int[emoticons.length];

        recursive(arr, 0, users, emoticons);




        return new int[]{plus, buy};
    }


    public void recursive(int[] arr, int startIdx, int[][] users, int[] emoticons){

        if(startIdx == arr.length){

            calc(arr, users, emoticons);
            return;
        }
        
        for(int i=10; i<=40; i+=10){

            arr[startIdx] = i;
            recursive(arr, startIdx+1 ,users, emoticons);
        }
    }

    private void calc(int[] arr, int[][] users, int[] emoticons){

        int cnt = 0;
        int buySum = 0;

        for(int i=0; i<users.length; i++){

            int userPer = users[i][0];
            int userLimit = users[i][1];
            int sum = 0;

            for(int j=0; j<arr.length; j++){

                if(arr[j] >= userPer){

                    sum += emoticons[j] * (100 - arr[j]) / 100;
                }
            }

            if(sum >= userLimit){

                // 유저 구매 상한보다 높으면 이모티콘 플러스 가입
                cnt++;
            } else{
                // 낮으면 그냥 구매
                buySum+=sum;
            }
        }
            if(cnt > plus){
                plus = cnt;
                buy = buySum;
            }
            if(cnt == plus){

                if(buy < buySum){
                    buy = buySum;
                }
            }
    }
}

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

문자열 name은 조이스틱으로 만들어야 하는 목표 이름을 의미
모든 문자는 A~Z로 구성되며, 시작 상태는 모두 'A'로 초기화됨

 

핵심 아이디어

세로 방향은 각 문자마다 A에서 목표 문자까지의 최소 조작 수를 계산
가로 방향은 커서를 어떻게 움직이면 최소인지 탐색하며 연속된 A 구간을 활용해 최적 경로 계산
가장 먼저 연속된 A 구간의 위치를 파악하고, 앞뒤로 돌아가는 여러 경로 중 이동 횟수가 가장 작은 경우를 선택
총 조작 횟수는 세로 조작 수의 합과 가로 조작 수를 더한 값

 

변수설명

alphabet은 알파벳 대문자 A~Z를 담은 문자열
answer는 최종 조작 횟수를 누적하는 변수
horizontal은 최소 좌우 이동 횟수를 계산하는 메서드
vertical은 문자 하나에 대한 최소 상하 이동 횟수를 계산하는 메서드
minMove는 가능한 커서 이동 경로 중 최소 이동 거리
moveCase1은 오른쪽 이동 후 뒤로 돌아가는 방식의 이동 거리
moveCase2는 끝까지 갔다가 왼쪽으로 되돌아오는 방식의 이동 거리
to는 현재 문자가 알파벳에서 몇 번째에 위치하는지 계산한 값

 

예시

name이 "JAZ"인 경우
J는 A에서 9번 이동
A는 그대로
Z는 A에서 1번 역방향 이동
가로 이동은 J → A → Z가 최적인 경우이므로
세로 조작 합은 9 + 0 + 1 = 10
가로 조작은 1
총 조작 횟수는 11

 

정답코드

package week_5;

public class week5_joystick {

    String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public int solution(String name) {
        int answer = 0;

        int horizontal = horizontal(name);
        for (char c : name.toCharArray()) {

            int vertical = vertical(c);

            System.out.println("A to " + c + ": " + vertical);
            answer += vertical;
        }
        return answer + horizontal;
    }

    private int horizontal(String name) {
        int len = name.length();
        int minMove = len - 1; // 초기값: 오른쪽으로 쭉 이동

        for (int i = 0; i < len; i++) {
            int next = i + 1;

            // 연속된 'A'가 있는 부분 skip
            while (next < len && name.charAt(next) == 'A') {
                next++;
            }

            // 처음부터 i까지 가고 → 뒤로 돌아가서 끝까지
            int moveCase1 = i * 2 + (len - next);
            // 끝까지 갔다가 < 돌아와서 i까지
            int moveCase2 = (len - next) * 2 + i;

            minMove = Math.min(minMove, Math.min(moveCase1, moveCase2));
        }

        return minMove;
    }

    private int vertical(char c) {

        // 여기에 위, 아래로 돌리는거 중 뭐가 더 빠른가 판단
        // 시작은 무조건 A
        int from = 0;
        int to = alphabet.indexOf(c);
        return Math.min(Math.abs(to - from), 26 - Math.abs(to - from));
    }
}

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

storage는 창고 상태를 나타내는 문자열 배열로 각 문자는 하나의 화물
requests는 작업 요청 목록으로 한 글자 요청은 지게차, 두 글자 이상은 크레인 작업을 의미

 

핵심 아이디어

storage를 2차원 배열로 변환하고 테두리를 만들어 외곽 판별을 쉽게 함
크레인 요청은 해당 알파벳을 전체 탐색하며 즉시 제거
지게차 요청은 BFS를 통해 바깥에서 접근 가능한 동일 알파벳 화물만 제거
모든 요청 수행 후 남아있는 화물의 개수를 반환

 

변수설명

input은 외곽 테두리를 포함한 전체 창고 상태를 담는 2차원 문자열 배열
border는 접근 가능 여부를 판단하는 마크 배열로 1은 접근 가능
dx, dy는 상하좌우 방향 이동을 위한 배열
q는 BFS 탐색에 사용되는 큐
visited는 BFS 중 방문 여부를 체크하는 배열
current는 현재 탐색 중인 좌표
target은 제거할 화물의 알파벳
count는 제거되지 않고 남아 있는 화물 수

 

예시

storage가 ["AB", "CD"], requests가 ["A", "B", "CD"]인 경우
"A"는 지게차 요청이므로 바깥에서 접근 가능한 "A"만 제거
"B"도 지게차 요청으로 같은 방식 수행
"CD"는 크레인 요청으로 "C", "D"를 전체 탐색하여 전부 제거
결과적으로 남은 화물의 수를 반환

 

정답코드

package week_5;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class week5_crain {


    int[][] border;


    public int solution(String[] storage, String[] requests) {
        int answer = 0;


        String[][] input = new String[storage.length+2][storage[0].length()+2];
        border = new int[input.length][input[0].length];
        for (int i = 0; i < input.length; i++) {
            for (int j = 0; j < input[0].length; j++) {
                if (i == 0 || i == input.length - 1 || j == 0 || j == input[0].length - 1) {
                    border[i][j] = 1;
                }
            }
        }
        // 주어진 화물 정보 이차원 배열로
        // 테두리는 null
        for(int i=0; i<=storage.length-1; i++){
            String origin = storage[i];
            for(int j=0; j<= storage[i].length()-1; j++){
                input[i+1][j+1] = String.valueOf(origin.charAt(j));
            }
        }

        for (String s : requests){
            if(s.length()>=2)
                crain(input, s.substring(0,1));
            else
                bfs(input, s);

        }


        return count(input);
    }

    // 지게차
    private void bfs(String[][] input, String target) {
        int[] dx = {0, 0, 1, -1};
        int[] dy = {1, -1, 0, 0};

        Queue<int[]> q = new LinkedList<>();
        int[][] visited = new int[input.length][input[0].length];

        q.add(new int[]{0, 0});
        visited[0][0] = 1;

        while (!q.isEmpty()) {
            int[] current = q.poll();
            int cx = current[0];
            int cy = current[1];

            for (int i = 0; i < 4; i++) {
                int nx = cx + dx[i];
                int ny = cy + dy[i];

                if (nx < 0 || ny < 0 || nx >= input.length || ny >= input[0].length) continue;
                if (visited[nx][ny] == 1) continue;

                visited[nx][ny] = 1;

                if (input[nx][ny] != null && input[nx][ny].equals(target)) {
                    border[nx][ny] = 1; // 근처에 있어서 접근 가능, 제거 대상
                } else if (input[nx][ny] == null) {
                    q.add(new int[]{nx, ny});
                }
            }
        }

        // 제거 수행
        for (int i = 0; i < input.length; i++) {
            for (int j = 0; j < input[0].length; j++) {
                if (border[i][j] == 1 && input[i][j] != null && input[i][j].equals(target)) {
                    input[i][j] = null;
                }
            }
        }
    }

    // 크레인 사용
    private void crain(String[][] input, String target){

        for(int i=0; i<input.length; i++){
            for(int j=0; j<input[0].length; j++){
                if(input[i][j] !=null && input[i][j].equals(target)){
                    input[i][j]=null;
                    border[i][j]=1;
                }
            }
        }
    }


    // 정답 count
    private int count(String[][] input) {
        int count = 0;
        for (int i = 0; i < input.length; i++) {
            for (int j = 0; j < input[0].length; j++) {
                if (input[i][j] != null) {
                    count++;
                }
            }
        }
        return count;
    }

}

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

입력

문자열 배열 maps는 미로의 정보를 담고 있으며 각 문자는 한 칸을 의미
'S'는 시작점, 'L'은 레버, 'E'는 도착점, 'O'는 빈칸, 'X'는 벽을 의미

 

핵심 아이디어

미로에서 S → L → E 순서로 이동할 수 있는 최단 경로를 각각의 BFS로 계산
시작점에서 레버까지, 레버에서 도착점까지 두 번의 경로 탐색 수행
각 경로가 존재하지 않으면 -1을 반환
두 경로가 모두 존재하는 경우 각각의 거리 합에 시작점과 레버, 레버와 도착점 간 이동을 포함해 총 거리 계산

 

변수설명

dx, dy는 4방향 이동을 위한 좌표 변화량
map은 문자열 배열 maps를 2차원 문자열 배열로 변환한 맵 정보
start, lever, end는 각각 S, L, E의 좌표를 담은 정수 배열
q는 BFS에 사용되는 탐색 큐
distance는 방문 여부 및 이동 거리를 기록하는 2차원 정수 배열
curX, curY는 현재 탐색 중인 좌표
newX, newY는 이동 후 좌표

 

예시

maps가 ["SOO", "OXL", "OEO"]인 경우
S에서 L까지의 최단 거리 2
L에서 E까지의 최단 거리 2
총 경로는 존재하며 이동 횟수는 2 + 2 + 2 = 6
결과는 6

 

정답코드

import java.util.*;

class Solution {
    static int[] dx = {0, 0 ,1, -1};
    static int[] dy = {1, -1, 0, 0};

    public int solution(String[] maps) {
        int answer = 0;

        String[][] map = new String[maps.length][maps[0].length()];

        int[] start = new int[2];
        int[] lever = new int[2];
        int[] end = new int[2];

        // String[] 배열을 map으로
        for(int i=0; i<maps.length;i++){
            for (int j = 0; j < maps[i].length(); j++) {
                char ch = maps[i].charAt(j);
                if(ch == 'S'){
                    map[i][j] = "S";
                    start[0] = i;
                    start[1] = j;
                } else if(ch == 'L'){
                    map[i][j] = "L";
                    lever[0] = i;
                    lever[1] = j;
                } else if(ch == 'E'){
                    map[i][j] = "E";
                    end[0] = i;
                    end[1] = j;
                }
                else if(ch == 'X')
                    map[i][j] = "X";
                else if(ch == 'O')
                    map[i][j] = "O";
            }
        }

        int a = bfs(map, start, lever);
        int b = bfs(map, lever, end);

        if(a != -1 && b != -1)
            return a+b+2;
        else return -1;

    }


    public int bfs(String[][] map, int[] start, int[] end){

        int n = map.length;
        int m = map[0].length;

        // bfs 사용을 위한 큐
        Queue<int[]> q = new LinkedList<>();

        // 방문 노드 체크
        int[][] distance = new int[map.length][map[0].length];
        for(int[] v : distance)
            Arrays.fill(v, -1);

        int curX = start[0];
        int curY = start[1];

        // q에 시작값 삽입
        q.add(new int[]{curX, curY});

        // 반복
        while(!q.isEmpty()){
            System.out.println(q.size());
            int[] now = q.poll();
            curX = now[0];
            curY = now[1];

            // 목적지 도착
            if (curX == end[0] && curY == end[1]) {
                return distance[curX][curY];
            }

            // 4방향 탐색
            for(int i=0; i<4; i++){
                int newX = curX+dx[i];
                int newY = curY+dy[i];

                // 미로 범위 바깥일 경우, 이미 방문한경우, 벽인경우 >> 무시
                if (newX < 0 || newX >= n || newY < 0 || newY >= m || distance[newX][newY] > 0 || map[newX][newY].equals("X")) {
                    continue;
                }

                // 방문횟수 + 1
                distance[newX][newY] = distance[curX][curY] + 1;
                q.add(new int[]{newX, newY});
            }
        }

        // 목적지까지 경로 없는경우 -1 return
        return -1;
    }

}

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

2차원 정수 배열 maps는 미로 정보를 담고 있으며 1은 이동 가능한 칸, 0은 벽을 의미
출발지는 좌상단 (0, 0), 도착지는 우하단 (n-1, m-1)

 

핵심 아이디어

너비 우선 탐색(BFS)으로 최단 경로를 탐색
큐를 사용해 탐색하며, 상하좌우 방향으로 이동
방문 여부를 visited 배열로 관리하고, 해당 칸까지의 이동 거리를 기록
목표 지점에 도달하면 해당 위치의 visited 값을 반환
도달하지 못하면 -1 반환

 

변수설명

dx, dy는 각각 상하좌우 방향 이동을 위한 x, y 좌표 변화량
visited는 각 위치의 방문 여부 및 시작 지점으로부터의 거리
q는 탐색할 위치를 담는 큐
cur은 현재 탐색 중인 위치
nextX, nextY는 다음에 탐색할 위치

 

예시

maps가
[[1,1,0,1],
[1,1,0,1],
[0,1,1,1],
[1,0,0,1],
[1,1,1,1]]인 경우
(0,0)에서 시작해 (4,3)까지 이동 가능한 최단 거리를 계산
BFS로 이동하며 방문 경로마다 거리를 누적
최단 경로의 길이는 9이므로 8을 반환한 뒤 +1 되어 최종 반환값은 9

 

 

정답코드

    public int solution(int[][] maps) {

        int answer = bfs(maps);
        return  answer == -1 ? -1 : answer + 1;
    }

    public int bfs(int[][] maps){
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};

        // 방문 노드
        int[][] visited = new int[maps.length][maps[0].length];
        for (int[] ints : visited) {
            Arrays.fill(ints, 0);
        }

        // 노드 큐
        Queue<int[]> q = new LinkedList<>();

        int[] start = {0,0};
        int[] end = {maps.length-1, maps[0].length-1};

        q.add(start);

        while(!q.isEmpty()){

            int[] cur = q.poll();

            // 도착지점
            if (cur[0] == end[0] && cur[1] == end[1]) {
                return visited[cur[0]][cur[1]];
            }
            
            // 4방향 탐색
            for (int n = 0; n < 4; n++) {
                int nextX = cur[0] + dx[n];
                int nextY = cur[1] + dy[n];

                // 범위 벗어났거나 벽일 경우, 이미 방문한 노드일 경우
                if (nextX < 0 || nextY < 0 || nextX >= maps.length || nextY >= maps[0].length || maps[nextX][nextY] == 0 || visited[nextX][nextY] != 0) {
                    continue;
                }

                visited[nextX][nextY] = visited[cur[0]][cur[1]] + 1;
                q.add(new int[]{nextX, nextY});
            }
        }
        return -1;
    }

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

정수 배열 players는 각 시간대별 접속자 수를 의미하며 길이는 24
정수 m은 서버 1대당 수용 가능한 최대 인원 수
정수 k는 한 번 증설된 서버가 유지되는 시간

 

핵심 아이디어

각 시간대마다 필요한 최소 서버 수를 계산
현재 시간에 배치된 서버 수가 부족하면 부족분만큼 서버를 증설
증설된 서버는 현재 시점부터 k시간 동안 적용되도록 모든 시점에 누적
누적 증설량은 시간 순으로 계산하며 매 시점마다 기록
마지막 시간대까지의 총 서버 증설 수량을 반환

 

변수설명

players는 0시부터 23시까지 각 시간대별 접속자 수를 저장한 배열
m은 서버 1대당 처리 가능한 최대 인원 수
k는 서버가 유지되는 시간
serverInfo[0]은 각 시간대별로 배치된 서버 수
serverInfo[1]은 해당 시점까지 누적된 서버 증설 수
need는 현재 시간에 필요한 서버 수
curServer는 현재 시간에 이미 배치된 서버 수
upgrade는 새로 증설해야 할 서버 수
i는 현재 시간 인덱스
j는 증설된 서버가 유지될 시간 인덱스

 

예시

players가 [20, 20, 30, 10, ...]이고 m이 10, k가 3인 경우
0시는 20명 접속으로 서버 2대 필요, 기존 서버 0대이므로 2대 증설
0시부터 2시까지 2대 서버가 유지됨
1시는 기존 서버 2대로 커버 가능하므로 추가 증설 없음
2시는 30명 접속으로 3대 필요, 현재 2대 있으므로 1대 추가
2시부터 4시까지 1대 추가 서버 유지
이 과정을 23시까지 반복해 최종 누적 서버 증설 수를 계산
serverInfo[1][23]을 반환

 

정답 코드

    public int solution(int[] players, int m, int k) {
        int[][] serverInfo = new int[2][24];
        Arrays.fill(serverInfo[0], 0);
        Arrays.fill(serverInfo[1], 0);

        for (int i = 0; i < 24; i++) {
            int need = players[i] / m;
            int curServer = serverInfo[0][i];

            if (need > curServer) {
                int upgrade = need - curServer;
                serverInfo[1][i] = (i == 0) ? need : serverInfo[1][i - 1] + upgrade;

                for (int j = i; j < i + k; j++) {
                    if (j <= 23) {
                        serverInfo[0][j] += upgrade;
                    } else {
                        break;
                    }
                }
            } else {
                serverInfo[1][i] = (i == 0) ? need : serverInfo[1][i - 1];
            }
        }
        return serverInfo[1][23];
    }

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

정수 n은 전체 숫자 후보의 개수
2차원 배열 q는 각 조건에 사용되는 숫자 묶음
정수 배열 ans는 q에 대응하는 정답 숫자 수

 

핵심 아이디어

1부터 n까지의 수 중에서 5개를 고르는 모든 조합을 생성
각 조합에 대해 조건 q와 정답 ans를 기준으로 유효한지 검사
각 조건은 선택된 조합 안에 해당 q[i]의 숫자 중 몇 개가 포함되는지를 체크
조건을 모두 만족하면 정답 개수를 증가
최종적으로 조건을 만족하는 조합의 개수를 반환

 

변수설명

arr는 1부터 n까지의 숫자를 담은 배열
answer는 조건을 만족하는 조합의 개수를 담는 AtomicInteger
depth와 start는 조합 생성을 위한 백트래킹 인덱스
q는 각 조건에 해당하는 숫자 배열
ans는 각 조건에 해당하는 정답 숫자 수
result는 현재 생성된 조합
check는 현재 조합이 모든 조건을 만족하는지 확인하는 함수
contains는 주어진 숫자가 배열 안에 존재하는지 여부를 반환

 

예시

n이 8이고 q가 [[1, 2, 3], [4, 5]]이며 ans가 [2, 1]인 경우
1부터 8까지 중 5개를 선택하는 모든 조합을 검사
각 조합에 대해 첫 번째 조건에서 1, 2, 3 중 2개가 포함되어야 하고
두 번째 조건에서는 4, 5 중 1개가 포함되어야 함
이 조건을 모두 만족하는 조합의 개수를 세어 반환

 

정답코드

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

public class week2_secretCode {

    public int solution(int n, int[][] q, int[] ans) {
        AtomicInteger answer = new AtomicInteger(0);

        int[] arr = new int[n];
        for(int i = 0; i < arr.length; i++) arr[i] = i+1;

        combination(arr, 0, 0, 5, q, ans, answer);

        return answer.get();
    }

    public void combination(int[] arr, int depth, int start, int r, int[][] q, int[] ans, AtomicInteger answer){

        if (depth == r) {

            if(check(q, ans, arr))
                answer.incrementAndGet();
            return;
        }

        for (int i = start; i < arr.length; i++) {

            swap(arr, depth, i);
            combination(arr, depth + 1, i + 1, r, q, ans, answer);
            swap(arr, depth, i);

        }
    }

    private void swap(int[] arr, int a, int b){

        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    public boolean check(int[][] q, int[] ans, int[] result){

        int cnt = 0;
        for(int i = 0; i < q.length; i++){
            for(int j = 0; j < q[i].length; j++){
                if(contains(q[i], result[j])){
                    cnt++;
                }
            }
            if(cnt != ans[i])
                return false;
            cnt=0;
        }
        return true;
    }

    public boolean contains(int[] arr, int target) {
        return Arrays.stream(arr).anyMatch(x -> x == target);
    }

 

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입력

정수 cacheSize는 캐시의 크기

cities는 도시 이름이 순서대로 저장된 문자열 배열

 

핵심 아이디어
도시 이름을 순서대로 처리하면서 캐시에서의 적중 여부에 따라 실행 시간을 계산
도시는 대소문자를 구분하지 않기 때문에 모두 소문자로 변환하여 비교
캐시에 도시가 이미 존재하면 실행 시간 1을 더하고, 해당 도시는 가장 앞에 다시 배치한
캐시에 도시가 없으면 실행 시간 5를 더하며, 캐시가 가득 찼을 경우 가장 오래된 항목을 제거
캐시는 LinkedList를 사용하여 삽입, 삭제를 효율적으로 처리

 

변수설명
cache는 현재 캐시 상태를 저장하는 LinkedList
answer는 전체 실행 시간을 누적하는 정수 변수
s는 현재 처리 중인 도시 이름이며, 모두 소문자로 변환

 

예시
cacheSize가 3이고 cities 배열이 ["Jeju", "Pangyo", "Seoul", "Jeju", "Pangyo", "Seoul"]인 경우,
처음 3개의 도시는 캐시에 없으므로 각각 5초가 소요되고 캐시에 삽입
그다음 3개의 도시는 모두 캐시에 존재하므로 각각 1초씩만 소요되어 총 실행 시간은 18초

 

정답코드

import java.util.Arrays;
import java.util.LinkedList;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        int answer = 0;
        if(cacheSize==0)
            return (int)Arrays.stream(cities).count()*5;

        LinkedList<String> cache = new LinkedList<>();

        for(String s : cities){

            s = s.toLowerCase();

            if(cache.remove(s)){
                answer += 1;
            } else {
                answer += 5;
                if(cache.size() == cacheSize)
                    cache.removeLast();
            }
            cache.push(s);

        }
        return answer;
    }
}

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

 

프로그래머스

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

programmers.co.kr

 

풀이

 

1. author 테이블과 book 테이블 inner join

book_id, author_id, category, author_name, book.price 정보를 담은 테이블 출력

 

2. 1번 테이블과 book_sales 테이블 inner join 

 

3. 작가번호, 이름, 카테고리로 그룹화 후 price * sales 집계

 

select distinct a.author_id, a.author_name, category, sum(price*sales) as total_sales
from 
(
select book_id, author.author_id, category, author_name, book.price
from book inner join author
on book.author_id = author.author_id
) as a inner join book_sales as b
on a.book_id = b.book_id
where date_format(b.sales_date,'%Y-%m') = '2022-01'
group by author_id, author_name, category
order by a.author_id, category desc

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

 

프로그래머스

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

programmers.co.kr

 

풀이

 

조건을 살펴보면

 

1. 자동차 종류가 SUV, 세단

2. 2022-11-01~ 2022-11-30 사이의 대여 기록이 없고

3. 30일 대여 금액이 50만원 이상 200만원 미만

 

 

위 조건을 토대로

 

1. 2022-11-01~ 2022-11-30 사이에 대여 기록이 존재하는 car_id 목록을 가진 테이블 추출

 

2. 30일 이상 대여 시, 할인율 계산을 위해

car_rental_company_car 과 car_rental_company_discount_plan 테이블을 inner join

조인 조건은 car_type 이 일치하고 duration_type 이 '30일 이상'

 

3. where 조건절에서 1번 테이블의 목록에 있는 car_id 는 11-01 ~ 11-30 사이에 대여가 불가능하므로 not in 으로 제외

car_type 이 세단, SUV 이고, 대여 가격이 50만원 이상 200만원 미만일 때 

 

4. car_id, car_type, fee(대여 가격 계산 후 floor 로 소수점 제거) 출력

 

5. order by 로 fee, car_type, car_id 각각 내림차순, 오름차순, 내림차순으로 정렬

 

 

select car.car_id, car.car_type, floor(car.daily_fee * ((100-discount.discount_rate)/100) * 30) as fee
from car_rental_company_car as car inner join car_rental_company_discount_plan as discount
on car.car_type = discount.car_type and
discount.duration_type = '30일 이상'
where 
car_id not in
(
    select distinct car_id
    from car_rental_company_rental_history
    where end_date > '2022-11-01' and start_date < '2022-12-01'
    order by car_id
 )
and (car.car_type = 'SUV' or car.car_type = '세단')
and ((car.daily_fee * 30 * (1-(discount.discount_rate)/100)) between 500000 and 2000000)
order by car.daily_fee * 30 * (1-(discount.discount_rate)/100) desc, car.car_type asc, car.car_id desc

+ Recent posts