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

 

프로그래머스

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

programmers.co.kr

문제 설명

ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다.

지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다.

위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다.
아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다.

  • 첫 번째 방법은 11개의 칸을 지나서 상대 팀 진영에 도착했습니다.
  • 두 번째 방법은 15개의 칸을 지나서 상대팀 진영에 도착했습니다.

위 예시에서는 첫 번째 방법보다 더 빠르게 상대팀 진영에 도착하는 방법은 없으므로, 이 방법이 상대 팀 진영으로 가는 가장 빠른 방법입니다.

만약, 상대 팀이 자신의 팀 진영 주위에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있습니다. 예를 들어, 다음과 같은 경우에 당신의 캐릭터는 상대 팀 진영에 도착할 수 없습니다.

게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.

제한사항
  • maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.
    • n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.
  • maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.
  • 처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.

 

입출력 예
maps answer
[[1,0,1,1,1],[1,0,1,0,1],[1,0,1,1,1],[1,1,1,0,1],[0,0,0,0,1]] 11
[[1,0,1,1,1],[1,0,1,0,1],[1,0,1,1,1],[1,1,1,0,0],[0,0,0,0,1]] -1
입출력 예 설명

입출력 예 #1
주어진 데이터는 다음과 같습니다.

캐릭터가 적 팀의 진영까지 이동하는 가장 빠른 길은 다음 그림과 같습니다.

따라서 총 11칸을 캐릭터가 지나갔으므로 11을 return 하면 됩니다.

입출력 예 #2
문제의 예시와 같으며, 상대 팀 진영에 도달할 방법이 없습니다. 따라서 -1을 return 합니다.


전형적인 BFS 문제다. N X N 에서 최단거리를 구할떄는 BFS! 이건 그냥 공식처럼 외워두자
BFS 를 돌려서 maps[N-1][M-1] 에 최종으로 도달했을때 저장되있는 값을 리턴, maps[N-1][M-1]에 방문한 적이 없으면
-1을 리턴!


import java.util.*;

class Solution {
    
    static boolean[][] visited; // 방문여부체크배열
    
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};
    
    static int N,M;       // 행, 열
    
    public int solution(int[][] maps) {
        int answer = 0;
        
        N = maps.length; // 열 (가로) -> x
        M = maps[0].length;    // 행 (세로) -> y
        
        visited = new boolean[N+1][M+1];
        
        BFS(0 ,0, maps); // BFS 시작
        
        if(visited[N-1][M-1])
            return maps[N-1][M-1];   
        else
            return -1;
    }
    public static void BFS(int y ,int x, int[][] maps){
        
        Queue<int[]> qu = new LinkedList<int[]>();
        
        qu.offer(new int[] {y, x});
        
        visited[y][x] = true;
        
        while(!qu.isEmpty()){
            int curY = qu.peek()[0];
            int curX = qu.peek()[1];
            
            qu.poll();
            
            for(int i =0; i<4; i++){
                int ny = curY + dy[i];
                int nx = curX + dx[i];
                
                //지도 범위내에서 벗어나면
                if(0 <= nx && 0 <= ny && nx < M && ny < N){
                    if(!visited[ny][nx] && maps[ny][nx] !=0){
                        qu.offer(new int[] {ny,nx});
                
                         maps[ny][nx] = maps[curY][curX] + 1;

                        visited[ny][nx] = true;
                    }           
                }
            }
        }
    }
}

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

 

프로그래머스

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

programmers.co.kr


문제 설명

오픈채팅방

카카오톡 오픈채팅방에서는 친구가 아닌 사람들과 대화를 할 수 있는데, 본래 닉네임이 아닌 가상의 닉네임을 사용하여 채팅방에 들어갈 수 있다.

신입사원인 김크루는 카카오톡 오픈 채팅방을 개설한 사람을 위해, 다양한 사람들이 들어오고, 나가는 것을 지켜볼 수 있는 관리자창을 만들기로 했다. 채팅방에 누군가 들어오면 다음 메시지가 출력된다.

"[닉네임]님이 들어왔습니다."

채팅방에서 누군가 나가면 다음 메시지가 출력된다.

"[닉네임]님이 나갔습니다."

채팅방에서 닉네임을 변경하는 방법은 다음과 같이 두 가지이다.

  • 채팅방을 나간 후, 새로운 닉네임으로 다시 들어간다.
  • 채팅방에서 닉네임을 변경한다.

닉네임을 변경할 때는 기존에 채팅방에 출력되어 있던 메시지의 닉네임도 전부 변경된다.

예를 들어, 채팅방에 "Muzi"와 "Prodo"라는 닉네임을 사용하는 사람이 순서대로 들어오면 채팅방에는 다음과 같이 메시지가 출력된다.

"Muzi님이 들어왔습니다."
"Prodo님이 들어왔습니다."

채팅방에 있던 사람이 나가면 채팅방에는 다음과 같이 메시지가 남는다.

"Muzi님이 들어왔습니다."
"Prodo님이 들어왔습니다."
"Muzi님이 나갔습니다."

Muzi가 나간후 다시 들어올 때, Prodo 라는 닉네임으로 들어올 경우 기존에 채팅방에 남아있던 Muzi도 Prodo로 다음과 같이 변경된다.

"Prodo님이 들어왔습니다."
"Prodo님이 들어왔습니다."
"Prodo님이 나갔습니다."
"Prodo님이 들어왔습니다."

채팅방은 중복 닉네임을 허용하기 때문에, 현재 채팅방에는 Prodo라는 닉네임을 사용하는 사람이 두 명이 있다. 이제, 채팅방에 두 번째로 들어왔던 Prodo가 Ryan으로 닉네임을 변경하면 채팅방 메시지는 다음과 같이 변경된다.

"Prodo님이 들어왔습니다."
"Ryan님이 들어왔습니다."
"Prodo님이 나갔습니다."
"Prodo님이 들어왔습니다."

채팅방에 들어오고 나가거나, 닉네임을 변경한 기록이 담긴 문자열 배열 record가 매개변수로 주어질 때, 모든 기록이 처리된 후, 최종적으로 방을 개설한 사람이 보게 되는 메시지를 문자열 배열 형태로 return 하도록 solution 함수를 완성하라.

제한사항
  • record는 다음과 같은 문자열이 담긴 배열이며, 길이는 1 이상 100,000 이하이다.
  • 다음은 record에 담긴 문자열에 대한 설명이다.
    • 모든 유저는 [유저 아이디]로 구분한다.
    • [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - "Enter [유저 아이디] [닉네임]" (ex. "Enter uid1234 Muzi")
    • [유저 아이디] 사용자가 채팅방에서 퇴장 - "Leave [유저 아이디]" (ex. "Leave uid1234")
    • [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - "Change [유저 아이디] [닉네임]" (ex. "Change uid1234 Muzi")
    • 첫 단어는 Enter, Leave, Change 중 하나이다.
    • 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다.
    • 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다.
    • 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다.
    • 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다.
입출력 예
record result
["Enter uid1234 Muzi", "Enter uid4567 Prodo","Leave uid1234","Enter uid1234 Prodo","Change uid4567 Ryan"] ["Prodo님이 들어왔습니다.", "Ryan님이 들어왔습니다.", "Prodo님이 나갔습니다.", "Prodo님이 들어왔습니다."]
입출력 예 설명

입출력 예 #1
문제의 설명과 같다.


문제 포인트

1. 'Enter' 인 경우 'id + 출력 메세지' al에 String 형태로 추가
2. 'Leave' 인 경우 '출력메세지'만 al에 String 형태로 추가
3. 'Change'인 경우 기존 map 저장되있는 id를 변경된 id로 바꿔서 map에 저장

마지막에 'id (key) + 출력메세지'로 저장되있는 al를 '님' 문자열 앞부분 기준으로 잘라서 map에서 get!
나온 닉네임(value)으로 '닉네임 + 출력메세지'로 출력


 

import java.util.*;

class Solution {
    public String[] solution(String[] record) {


        HashMap<String, String> map = new HashMap<>();
        ArrayList<String> al = new ArrayList<>();

        // 각 명령어 대로 key+"님이 ~~~" 형식으로 al에 저장
        for (String str : record) {

            String command[] = str.split(" ");

            switch (command[0]) {

                // 들어온경우 Map 에 Key를 ID , value를 닉네임으로 저장 (uid1234 , Muzi) 
                // 들어온 id + 메세지 al에 추가
                case "Enter":
                    map.put(command[1], command[2]);
                    al.add(command[1] + "님이 들어왔습니다.");
                    break;
                // 나가는 경우 나가는 아이디 + 메세지만 al에 추가
                case "Leave":
                    al.add(command[1] + "님이 나갔습니다.");
                    break;
                // 해당  key 값에 대한 value 만 변경
                case "Change":
                    map.replace(command[1], command[2]);
                    break;
            }
        }

        // record 의 크기로 선언해주면 change 명령어까지 카운트 되므로 al.size로 선언 (메세지 출력수)  
        String[] answer = new String[al.size()];

        for (int i = 0; i < al.size(); i++) {
            String tmp = al.get(i);
            int idx = tmp.indexOf('님'); // '님'이 나오는 인덱스를 기억해서
            String key_id = tmp.substring(0, idx); // '님'이 나오기 직전 idx 까지 key_id 에 저장
            answer[i] = tmp.replace(key_id, map.get(key_id)); // key_id를 value 로 replace 로 하여 answer[i] 에 저장
        }

        return answer;
    }
}

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

 

프로그래머스

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

programmers.co.kr

문제 설명

주차장의 요금표와 차량이 들어오고(입차) 나간(출차) 기록이 주어졌을 때, 차량별로 주차 요금을 계산하려고 합니다. 아래는 하나의 예시를 나타냅니다.

  • 요금표

기본 시간(분)기본 요금(원)단위 시간(분)단위 요금(원)

180 5000 10 600

 

  • 입/출차 기록

시각(시:분)차량 번호내역

05:34 5961 입차
06:00 0000 입차
06:34 0000 출차
07:59 5961 출차
07:59 0148 입차
18:59 0000 입차
19:09 0148 출차
22:59 5961 입차
23:00 5961 출차

 

  • 자동차별 주차 요금

차량 번호누적 주차 시간(분)주차 요금(원)

0000 34 + 300 = 334 5000 + ⌈(334 - 180) / 10⌉ x 600 = 14600
0148 670 5000 +⌈(670 - 180) / 10⌉x 600 = 34400
5961 145 + 1 = 146 5000
  • 어떤 차량이 입차된 후에 출차된 내역이 없다면, 23:59에 출차된 것으로 간주합니다.
    • 0000번 차량은 18:59에 입차된 이후, 출차된 내역이 없습니다. 따라서, 23:59에 출차된 것으로 간주합니다.
  • 00:00부터 23:59까지의 입/출차 내역을 바탕으로 차량별 누적 주차 시간을 계산하여 요금을 일괄로 정산합니다.
  • 누적 주차 시간이 기본 시간이하라면, 기본 요금을 청구합니다.
  • 누적 주차 시간이 기본 시간을 초과하면, 기본 요금에 더해서, 초과한 시간에 대해서 단위 시간 마다 단위 요금을 청구합니다.
    • 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림합니다.
    • ⌈a⌉ : a보다 작지 않은 최소의 정수를 의미합니다. 즉, 올림을 의미합니다.

주차 요금을 나타내는 정수 배열 fees, 자동차의 입/출차 내역을 나타내는 문자열 배열 records가 매개변수로 주어집니다. 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아서 return 하도록 solution 함수를 완성해주세요.

제한사항

  • fees의 길이 = 4
    • fees[0] = 기본 시간(분)
    • 1 ≤ fees[0] ≤ 1,439
    • fees[1] = 기본 요금(원)
    • 0 ≤ fees[1] ≤ 100,000
    • fees[2] = 단위 시간(분)
    • 1 ≤ fees[2] ≤ 1,439
    • fees[3] = 단위 요금(원)
    • 1 ≤ fees[3] ≤ 10,000
  • 1 ≤ records의 길이 ≤ 1,000
    • records의 각 원소는 "시각 차량번호 내역" 형식의 문자열입니다.
    • 시각, 차량번호, 내역은 하나의 공백으로 구분되어 있습니다.
    • 시각은 차량이 입차되거나 출차된 시각을 나타내며, HH:MM 형식의 길이 5인 문자열입니다.
      • HH:MM은 00:00부터 23:59까지 주어집니다.
      • 잘못된 시각("25:22", "09:65" 등)은 입력으로 주어지지 않습니다.
    • 차량번호는 자동차를 구분하기 위한, `0'~'9'로 구성된 길이 4인 문자열입니다.
    • 내역은 길이 2 또는 3인 문자열로, IN 또는 OUT입니다. IN은 입차를, OUT은 출차를 의미합니다.
    • records의 원소들은 시각을 기준으로 오름차순으로 정렬되어 주어집니다.
    • records는 하루 동안의 입/출차된 기록만 담고 있으며, 입차된 차량이 다음날 출차되는 경우는 입력으로 주어지지 않습니다.
    • 같은 시각에, 같은 차량번호의 내역이 2번 이상 나타내지 않습니다.
    • 마지막 시각(23:59)에 입차되는 경우는 입력으로 주어지지 않습니다.
    • 아래의 예를 포함하여, 잘못된 입력은 주어지지 않습니다.
      • 주차장에 없는 차량이 출차되는 경우
      • 주차장에 이미 있는 차량(차량번호가 같은 차량)이 다시 입차되는 경우

입출력 예

fees records result
[180, 5000, 10, 600] ["05:34 5961 IN", "06:00 0000 IN", "06:34 0000 OUT", "07:59 5961 OUT", "07:59 0148 IN", "18:59 0000 IN", "19:09 0148 OUT", "22:59 5961 IN", "23:00 5961 OUT"] [14600, 34400, 5000]
[120, 0, 60, 591] ["16:00 3961 IN","16:00 0202 IN","18:00 3961 OUT","18:00 0202 OUT","23:58 3961 IN"] [0, 591]
[1, 461, 1, 10] ["00:00 1234 IN"] [14841]

입출력 예 설명

입출력 예 #1

문제 예시와 같습니다.

입출력 예 #2

  • 요금표

기본 시간(분)기본 요금(원)단위 시간(분)단위 요금(원)

120 0 60 591

 

  • 입/출차 기록

시각(시:분)차량 번호내역

16:00 3961 입차
16:00 0202 입차
18:00 3961 출차
18:00 0202 출차
23:58 3961 입차

 

  • 자동차별 주차 요금

차량 번호누적 주차 시간(분)주차 요금(원)

0202 120 0
3961 120 + 1 = 121 0 +[(121 - 120) / 60]x 591 = 591
  • 3961번 차량은 2번째 입차된 후에는 출차된 내역이 없으므로, 23:59에 출차되었다고 간주합니다.

 

입출력 예 #3

  • 요금표

기본 시간(분)기본 요금(원)단위 시간(분)단위 요금(원)

1 461 1 10

 

  • 입/출차 기록

시각(시:분)차량 번호내역

00:00 1234 입차

 

  • 자동차별 주차 요금

차량 번호누적 주차 시간(분)주차 요금(원)

1234 1439 461 +[(1439 - 1) / 1]x 10 = 14841
  • 1234번 차량은 출차 내역이 없으므로, 23:59에 출차되었다고 간주합니다.

 

 


import java.util.*;

class Solution {
    public int[] solution(int[] fees, String[] records) {
        int[] answer = {};
        // 기본 시간(분) / 기본 요금(원) / 단위 시간(분) /단위 요금(원)

        HashMap<String, Integer> map = new HashMap<>();
        HashMap<String, Integer> result_map = new HashMap<>();      // 결과값 저장

        // 주차시간 누적시키기
        for (int i = 0; i < records.length; i++) {
            String car_record[] = records[i].split(" ");

            if (car_record[2].equals("IN")) {
                // 입차일 경우 ( 차량번호(key) , 입차시간(value) ) 형태로 map 에 저장
                map.put(car_record[1], hourtomin(car_record[0]));
            } else if (car_record[2].equals("OUT")) {
                // 출차일 경우
                int parking_time = map.get(car_record[1]);   // 주차시간
                int exiting_time = hourtomin(car_record[0]); // 출차시간

                int cal_time = exiting_time - parking_time; // 계산해야되는 시간(분)

                if (result_map.get(car_record[1]) == null)
                    result_map.put(car_record[1], cal_time);
                else
                    result_map.put(car_record[1], result_map.get(car_record[1]) + cal_time);

                map.remove(car_record[1]);
            }
        }

        // 남은 차 계산
        for (String key : map.keySet()) {
            int time = 0;
            if (result_map.get(key) != null)
                time = result_map.get(key);

            int cal_time = 1439 - map.get(key);

            result_map.put(key, time + cal_time);
        }

        List<String> al = new ArrayList<>(result_map.keySet());

        // 키 값으로 오름차순 정렬
        Collections.sort(al);

        answer = new int[al.size()];
        int idx = 0;

        // 금액계산
        for (String key : al) {

            int time = result_map.get(key); // 해당 차의 주차 총 시간 (분)

            // 기본시간보다 적으면
            if (time <= fees[0]) {
//                result_map.put(key, fees[1]);
                answer[idx] = fees[1];
            }
            // 기본시간보다 많으면
            else {
                double tmp = Math.ceil((time - fees[0]) / (double) fees[2]);
                answer[idx] = fees[1] + (int) tmp * fees[3];
            }
            idx++;
        }

        return answer;
    }

    public int hourtomin(String time) {
        String tmp[] = time.split(":");
        int hour = Integer.parseInt(tmp[0]); // 시간
        int minutes = Integer.parseInt(tmp[1]); // 분

        return hour * 60 + minutes;
    }
}

 

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

 

프로그래머스

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

programmers.co.kr

문제 설명

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.
전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.

  • 구조대 : 119
  • 박준영 : 97 674 223
  • 지영석 : 11 9552 4421

전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요.

제한 사항
  • phone_book의 길이는 1 이상 1,000,000 이하입니다.
    • 각 전화번호의 길이는 1 이상 20 이하입니다.
    • 같은 전화번호가 중복해서 들어있지 않습니다.
입출력 예제
phone_book return
["119", "97674223", "1195524421"] false
["123","456","789"] true
["12","123","1235","567","88"] false
입출력 예 설명

입출력 예 #1
앞에서 설명한 예와 같습니다.

입출력 예 #2
한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.

입출력 예 #3
첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.


문제 포인트

처음에 직관적으로 2중 포문을 돌려서 해당 전화번호가 앞에 있으면 접두어인 걸로 구현하였으나 그렇게 하면 효율성 false,,,, 다른 방법 찾아보니 Collections.sort(al); 해서 바로 옆끼리만 체크하면 되는 방법.. 발견.... 천재다... 

※ List<Sring> al = Arrays.asList(phone_book) <- 이것도 기억해두자 Array 를 ArrayList로 변환하는 방법


// 119 , 12119 테스트케이스 추가해보기
import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;

        List<String> al = Arrays.asList(phone_book);

        Collections.sort(al);

        for (int i = 0; i < al.size() - 1; i++) {

            // 
            if (al.get(i+1).contains(al.get(i)) && al.get(i+1).charAt(0) == al.get(i).charAt(0)) {
                answer = false;
                break;
            }
//            String cur = al.get(i);
//            String target = al.get(i + 1).substring(0, cur.length());
//            if (cur.equals(target)) {
//                answer = false;
//                break;
//            }
        }

        /* 효율성 테스트 실패
//        String prefix = phone_book[0];
//        int prefix_length = prefix.length();
//        Loop1:
//        for (int i = 0; i < phone_book.length; i++) {
//            String cur = phone_book[i];
//            int cur_length = cur.length();
//
//            for (int j = i + 1; j < phone_book.length; j++) {
//                if (cur_length <= phone_book[j].length()) {
//                    String target = phone_book[j].substring(0, cur_length);
//
//                    if (target.equals(cur)) {
//                        answer = false;
//                        break Loop1;
//                    }
//                }
//            }
//        }

         */
        return answer;
    }
}

 

 

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

 

프로그래머스

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

programmers.co.kr

문제 설명

스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.

예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.

종류이름
얼굴 동그란 안경, 검정 선글라스
상의 파란색 티셔츠
하의 청바지
겉옷 긴 코트

스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

제한사항
  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
  • 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
  • 같은 이름을 가진 의상은 존재하지 않습니다.
  • clothes의 모든 원소는 문자열로 이루어져 있습니다.
  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.
  • 스파이는 하루에 최소 한 개의 의상은 입습니다.
입출력 예
clothes return
[["yellow_hat", "headgear"], ["blue_sunglasses", "eyewear"], ["green_turban", "headgear"]] 5
[["crow_mask", "face"], ["blue_sunglasses", "face"], ["smoky_makeup", "face"]] 3
입출력 예 설명

예제 #1
headgear에 해당하는 의상이 yellow_hat, green_turban이고 eyewear에 해당하는 의상이 blue_sunglasses이므로 아래와 같이 5개의 조합이 가능합니다.

1. yellow_hat
2. blue_sunglasses
3. green_turban
4. yellow_hat + blue_sunglasses
5. green_turban + blue_sunglasses

예제 #2
face에 해당하는 의상이 crow_mask, blue_sunglasses, smoky_makeup이므로 아래와 같이 3개의 조합이 가능합니다.

1. crow_mask
2. blue_sunglasses
3. smoky_makeup

문제포인트

문제가 길어 복잡해보이지만 조금만 생각하면 단순하게 풀수있는 문제였다. HaspMap 에 (옷 종류, 해당 옷 분류의 수)를 put하여서 조합되어 나오는 경우의 수를 구하였다. 쉬었던 문제!!


import java.util.*;

class Solution {
    public int solution(String[][] clothes) {
        int answer = 1;

        HashMap<String, Integer> map = new HashMap<>();

        for (int i = 0; i < clothes.length; i++) {
            String key = clothes[i][1];

            if (map.containsKey(key)) map.put(clothes[i][1], map.get(key) + 1);
            else map.put(key, 1);

        }

        for (String str : map.keySet())
            answer *= map.get(str)+1;

        // 아얘 안입는 경우 빼야됨
        return answer-1;
    }
}

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

 

프로그래머스

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

programmers.co.kr

문제 설명

무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다.

예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.

구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.

사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성해주세요.

제한사항
  • 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
  • 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.
입출력 예
[70, 50, 80, 50] 100 3
[70, 80, 50] 100 3

문제 포인트

1. 가장 무거운 사람과 가장 가벼운 사람끼리 조합해서 구명보트에 태워야됨. 가장 무거운사람 +가장 가벼운사람 조합이 보트무게 제한보다 적을 경우, j++, 해주어 해당 가벼운 사람을 태워서 다음 가벼운사람이랑 조합하도록 구현,

Greedy -> 현재 선택할수 있는 최선의 선택을 반복★★

2. 문제 꼼꼼히 읽고 손코딩 해본다음에 코드로 옮기는 걸로 연습해보자...... 바로 코드짜다가 꼬이네 계속


import java.util.*;

class Solution {
    public int solution(int[] people, int limit) {
        int answer = 0;
        
        Arrays.sort(people); // {50, 50, 70, 80}
        
        int j = 0;
        
        for(int i = people.length-1; j <= i; i--){
            if(people[i] + people[j] <= limit)
                j++;
            
            answer++;
        }
        
        return answer;
    }
}

https://www.acmicpc.net/problem/10026

 

10026번: 적록색약

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록)

www.acmicpc.net


1. 현재 위치와 같은 문자가 나오는 경우 계속 DFS 로 방문하게 되는 함수 DFS
2. R과 G가 같은 문자로 인식되므로 flag 변수를 따로 생성하여 R 혹은 G인경우 flag 변수를 true 값으로 설정하여
분류하였다.


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    static int RGB = 0, RGB2 = 0;
    static int N;
    static boolean flag;
    static char map[][];
    static boolean visited[][];
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};

    public static void main(String[] agrs) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());

        map = new char[N + 1][N + 1];
        visited = new boolean[N + 1][N + 1];

        for (int i = 1; i <= N; i++) {
            String tmp = br.readLine();
            for (int j = 1; j <= tmp.length(); j++) {
                map[i][j] = tmp.charAt(j - 1);
            }
        }

        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                // 방문한 적이 없으면
                if (!visited[i][j]) {
                    DFS(i, j);
                    RGB++;
                }
            }
        }
        visited = new boolean[N + 1][N + 1];

        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                // 방문한 적이 없으면
                if (!visited[i][j]) {
                    DFS2(i, j);
                    RGB2++;
                }
            }
        }

        System.out.println(RGB+" "+ RGB2);
    }

    static void DFS(int y, int x) {
        visited[y][x] = true;

        char cur = map[y][x];

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

            if (ny < 0 || nx < 0 || N < ny || N < nx)
                continue;

            if (!visited[ny][nx] && map[ny][nx] == cur)
                DFS(ny, nx);
        }
    }

    static void DFS2(int y, int x) {
        visited[y][x] = true;

        char cur = map[y][x];

        // R 혹은 G 인경우는 flag = true
        if (cur == 'R' || cur == 'G')
            flag = true;
        else
            flag = false;


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

            if (ny < 0 || nx < 0 || N < ny || N < nx)
                continue;

            if (visited[ny][nx])
                continue;
            
            // flag 가 true 인경우는 R,G 인경우 이므로
            if (flag && (map[ny][nx] == 'R' || map[ny][nx] == 'G')){
                DFS2(ny, nx);
            }
            else if (!flag && map[ny][nx] == 'B'){
                DFS2(ny, nx);
            }
        }
    }
}

https://www.acmicpc.net/problem/4963

 

4963번: 섬의 개수

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도

www.acmicpc.net


단순한 BFS문제이다. 동서남북만 생각해주는것이 아니라 대각선 방향까지 생각해줘야하기떄문에 
dy, dx 배열을 8가지 방향으로 나눠서 생각해야 했다. 

static 변수랑 BFS 내부에 있는 변수랑 이름을 똑같이 만들어버려서 오랫동안 헤맸다..


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {

    static int w, h, cnt = 0;
    static int map[][];
    static boolean visited[][];
    static int[] dy = {1, 0, -1, 0, 1, 1, -1, -1};
    static int[] dx = {0, 1, 0, -1, 1, -1, 1, -1};

    public static void main(String[] agrs) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
        StringBuilder sb = new StringBuilder();


        while (true) {
            st = new StringTokenizer(br.readLine());
            w = Integer.parseInt(st.nextToken()); // 너비
            h = Integer.parseInt(st.nextToken()); // 높이

            // 입력값 0,0 이 나오면 break
            if (w == 0 && h == 0) break;

            map = new int[h + 1][w + 1];
            visited = new boolean[h + 1][w + 1];

            // 입력하는대로 map 초기화
            for (int i = 1; i <= h; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 1; j <= w; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                }
            }

            for (int i = 1; i <= h; i++) {
                for (int j = 1; j <= w; j++) {
                    if (!visited[i][j] && map[i][j] == 1) {
                        BFS(i, j);
                        cnt++;
                    }
                }
            }

            sb.append(cnt + "\n");

            cnt = 0;
        }

        System.out.println(sb);
    }

    static void BFS(int y, int x) {
        Queue<int[]> qu = new LinkedList<>();
        qu.offer(new int[]{y, x});

        visited[y][x] = true;

        while (!qu.isEmpty()) {
            int curY = qu.peek()[0];
            int curX = qu.peek()[1];

            qu.poll();

            for (int i = 0; i < 8; i++) {
                int ny = curY + dy[i];
                int nx = curX + dx[i];

                if (ny < 1 || nx < 1 || ny > h || nx > w)
                    continue;

                if (visited[ny][nx] || map[ny][nx] == 0)
                    continue;

                visited[ny][nx] = true;
                qu.offer(new int[]{ny, nx});
            }
        }
    }
}

https://www.acmicpc.net/problem/11047

 

11047번: 동전 0

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)

www.acmicpc.net


그리디 알고리즘을 활용한 단순한 문제이다.
가장 큰수 부터 나눠지는대로 나눠서 몫을 cnt 값에 더해주기만 하면 끝이다.


 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] agrs) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int N = Integer.parseInt(st.nextToken());
		int K = Integer.parseInt(st.nextToken());
		int cnt = 0;

		int[] A = new int[N];

		for (int i = 0; i < N; i++)
			A[i] = Integer.parseInt(br.readLine());

		for (int i = N - 1; 0 <= i; i--) {
			int quotient = K / A[i]; // 몫

			if (quotient == 0)
				continue;
			else {
				K = K - A[i] * quotient;
				cnt += quotient;
			}
		}
		System.out.println(cnt);
	}
}

 

https://www.acmicpc.net/problem/4949

 

4949번: 균형잡힌 세상

하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다. 각 줄은 마침표(".")로 끝난다

www.acmicpc.net


풀이 

어렵게 생각하면 어렵고 쉽게 생각하면 쉬운 문제였다.
많은 문자열을 입력받지만, 우리가 생각해야될 것은 괄호 뿐이므로 '(', ')', '[', ']'가 들어오는 경우만
생각해주면 된다.

'(' , '['이 들어오는 경우는 Stack에 Push 하였고
')', ']' 이 들어오는 경우는 앞에 여는 괄호가 일치한지만 판단하여 pop하였다.

 

기타

풀다가 문자열을 비교할 때 equals 와 == 차이가 궁금해서 글로 한번 요약 정리 해보았다.

https://studywithus.tistory.com/88

 

[JAVA] 문자열 비교하기 String에서 ==와 equals 의 차이

Java에서 int와 boolean과 같은 일반적인 데이터 타입의 비교는 ==이라는 연산자를 사용하여 비교합니다. 하지만 String처럼 Class의 값을 비교할때는 ==이 아닌 equals()라는 메소드를 사용하여 비교를 합

studywithus.tistory.com

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;

public class Main {

	public static void main(String[] agrs) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		while (true) {
			String input = br.readLine();

			if (input.equals("."))
				break;

			sb.append(solve(input) + '\n');
		}
		System.out.println(sb);
	}

	static String solve(String input) {

		Stack<Character> stack = new Stack<Character>();

		for (int i = 0; i < input.length(); i++) {
			char c = input.charAt(i);

			if (c == '(' || c == '[')
				stack.push(c);

			if (c == ')') {
				if (stack.isEmpty() || stack.peek() != '(')
					return "no";
				else
					stack.pop();
			}

			if (c == ']') {
				if (stack.isEmpty() || stack.peek() != '[')
					return "no";
				else
					stack.pop();
			}
		}

		if (stack.isEmpty())
			return "yes";
		else
			return "no";
	}
}

+ Recent posts