문제설명

더보기

지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.

  • ["방향 거리", "방향 거리" … ]

예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.

  • 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
  • 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.

위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.

공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하도록 solution 함수를 완성해주세요.


제한사항

  • 3 ≤ park의 길이 ≤ 50
    • 3 ≤ park[i]의 길이 ≤ 50
      • park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
        • S : 시작 지점
        • O : 이동 가능한 통로
        • X : 장애물
    • park는 직사각형 모양입니다.
  • 1 ≤ routes의 길이 ≤ 50
    • routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
    • 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
    • routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
      • op는 다음 네 가지중 하나로 이루어져 있습니다.
        • N : 북쪽으로 주어진 칸만큼 이동합니다.
        • S : 남쪽으로 주어진 칸만큼 이동합니다.
        • W : 서쪽으로 주어진 칸만큼 이동합니다.
        • E : 동쪽으로 주어진 칸만큼 이동합니다.
      • 1 ≤ n ≤ 9

입출력 예

parkroutesresult
["SOO","OOO","OOO"] ["E 2","S 2","W 1"] [2,1]
["SOO","OXX","OOO"] ["E 2","S 2","W 1"] [0,1]
["OSO","OOO","OXO","OOO"] ["E 2","S 3","W 1"] [0,0]

입출력 예 설명

입출력 예 #1

입력된 명령대로 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동하면 [0,0] -> [0,2] -> [2,2] -> [2,1]이 됩니다.

입출력 예 #2

입력된 명령대로라면 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동해야하지만 남쪽으로 2칸 이동할 때 장애물이 있는 칸을 지나기 때문에 해당 명령을 제외한 명령들만 따릅니다. 결과적으로는 [0,0] -> [0,2] -> [0,1]이 됩니다.

입출력 예 #3

처음 입력된 명령은 공원을 나가게 되고 두 번째로 입력된 명령 또한 장애물을 지나가게 되므로 두 입력은 제외한 세 번째 명령만 따르므로 결과는 다음과 같습니다. [0,1] -> [0,0]

 

1. 장애물을 만나거나 벽에 부딪히면 해당 명령을 전부 무시해야 하기때문에 한칸씩 저장하는 것이 아니라 명령단위로 시작 위치를 저장해줘야함

 

import java.util.*;
class Solution {
    public int[] solution(String[] park, String[] routes) {
        int[] answer = {0,0};
    
        final int H = park.length; //세로
        final int W = park[0].length(); // 가로
        
        for(int i=0; i< H; i++){ // 지도만들기, 시작위치 찾기
            boolean check = false;
            for(int j=0; j< W; j++){
                if(park[i].charAt(j)=='S'){ 
                    answer[0] = i;
                    answer[1] = j;
                    check = true;
                    break;
                }
            }
            if(check) break;
        }
        
        //루트 나누기
        for(String rut : routes){
            String way = rut.split(" ")[0]; //방향
            int move = Integer.parseInt(rut.split(" ")[1]); //이동거리
            int posy = answer[0];
            int posx = answer[1];
            
            for(int i=0; i<move; i++){ //일단 해당위치로 한칸 이동하기
                if(way.equals("E")){
                    posx++;
                }
                if(way.equals("W")){
                    posx--;
                }
                if(way.equals("S")){
                    posy++;
                }
                if(way.equals("N")){
                    posy--;
                }
                if(posx>=0 && posy>=0 && posx<W && posy<H){ //이동한 상태에서 장애물 확인하고 위치 저장하기
                    if(park[posy].charAt(posx) == 'X') break;
                    if(i==move-1){ // 마지막 이동시 일괄저장
                        answer[0] = posy;
                        answer[1] = posx;
                    }
                }
            }
        }
        return answer;
    }
}
더보기

나만의 카카오 성격 유형 검사지를 만들려고 합니다.
성격 유형 검사는 다음과 같은 4개 지표로 성격 유형을 구분합니다. 성격은 각 지표에서 두 유형 중 하나로 결정됩니다.

지표 번호성격 유형
1번 지표 라이언형(R), 튜브형(T)
2번 지표 콘형(C), 프로도형(F)
3번 지표 제이지형(J), 무지형(M)
4번 지표 어피치형(A), 네오형(N)

4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.

검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.

  • 매우 비동의
  • 비동의
  • 약간 비동의
  • 모르겠음
  • 약간 동의
  • 동의
  • 매우 동의

각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.

예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수 있습니다.

선택지성격 유형 점수
매우 비동의 네오형 3점
비동의 네오형 2점
약간 비동의 네오형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 어피치형 1점
동의 어피치형 2점
매우 동의 어피치형 3점

이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(A) 성격 유형 1점을 받게 됩니다. 만약 검사자가 매우 비동의 선택지를 선택할 경우 네오형(N) 성격 유형 3점을 받게 됩니다.

위 예시처럼 네오형이 비동의, 어피치형이 동의인 경우만 주어지지 않고, 질문에 따라 네오형이 동의, 어피치형이 비동의인 경우도 주어질 수 있습니다.
하지만 각 선택지는 고정적인 크기의 점수를 가지고 있습니다.

  • 매우 동의나 매우 비동의 선택지를 선택하면 3점을 얻습니다.
  • 동의나 비동의 선택지를 선택하면 2점을 얻습니다.
  • 약간 동의나 약간 비동의 선택지를 선택하면 1점을 얻습니다.
  • 모르겠음 선택지를 선택하면 점수를 얻지 않습니다.

검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단합니다. 단, 하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단합니다.

질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가 각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가 매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return 하도록 solution 함수를 완성해주세요.


제한사항

  • 1 ≤ survey의 길이 ( = n) ≤ 1,000
    • survey의 원소는 "RT", "TR", "FC", "CF", "MJ", "JM", "AN", "NA" 중 하나입니다.
    • survey[i]의 첫 번째 캐릭터는 i+1번 질문의 비동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.
    • survey[i]의 두 번째 캐릭터는 i+1번 질문의 동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.
  • choices의 길이 = survey의 길이
    • choices[i]는 검사자가 선택한 i+1번째 질문의 선택지를 의미합니다.
    • 1 ≤ choices의 원소 ≤ 7
    choices뜻
    1 매우 비동의
    2 비동의
    3 약간 비동의
    4 모르겠음
    5 약간 동의
    6 동의
    7 매우 동의

입출력 예

surveychoicesresult
["AN", "CF", "MJ", "RT", "NA"] [5, 3, 2, 7, 5] "TCMA"
["TR", "RT", "TR"] [7, 1, 3] "RCJA"

입출력 예 설명

입출력 예 #1

1번 질문의 점수 배치는 아래 표와 같습니다.

선택지성격 유형 점수
매우 비동의 어피치형 3점
비동의 어피치형 2점
약간 비동의 어피치형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 네오형 1점
동의 네오형 2점
매우 동의 네오형 3점

1번 질문에서는 지문의 예시와 다르게 비동의 관련 선택지를 선택하면 어피치형(A) 성격 유형의 점수를 얻고, 동의 관련 선택지를 선택하면 네오형(N) 성격 유형의 점수를 얻습니다.
1번 질문에서 검사자는 약간 동의 선택지를 선택했으므로 네오형(N) 성격 유형 점수 1점을 얻게 됩니다.

2번 질문의 점수 배치는 아래 표와 같습니다.

선택지성격 유형 점수
매우 비동의 콘형 3점
비동의 콘형 2점
약간 비동의 콘형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 프로도형 1점
동의 프로도형 2점
매우 동의 프로도형 3점

2번 질문에서 검사자는 약간 비동의 선택지를 선택했으므로 콘형(C) 성격 유형 점수 1점을 얻게 됩니다.

3번 질문의 점수 배치는 아래 표와 같습니다.

선택지성격 유형 점수
매우 비동의 무지형 3점
비동의 무지형 2점
약간 비동의 무지형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 제이지형 1점
동의 제이지형 2점
매우 동의 제이지형 3점

3번 질문에서 검사자는 비동의 선택지를 선택했으므로 무지형(M) 성격 유형 점수 2점을 얻게 됩니다.

4번 질문의 점수 배치는 아래 표와 같습니다.

선택지성격 유형 점수
매우 비동의 라이언형 3점
비동의 라이언형 2점
약간 비동의 라이언형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 튜브형 1점
동의 튜브형 2점
매우 동의 튜브형 3점

4번 질문에서 검사자는 매우 동의 선택지를 선택했으므로 튜브형(T) 성격 유형 점수 3점을 얻게 됩니다.

5번 질문의 점수 배치는 아래 표와 같습니다.

선택지성격 유형 점수
매우 비동의 네오형 3점
비동의 네오형 2점
약간 비동의 네오형 1점
모르겠음 어떤 성격 유형도 점수를 얻지 않습니다
약간 동의 어피치형 1점
동의 어피치형 2점
매우 동의 어피치형 3점

5번 질문에서 검사자는 약간 동의 선택지를 선택했으므로 어피치형(A) 성격 유형 점수 1점을 얻게 됩니다.

1번부터 5번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

지표 번호성격 유형점수성격 유형점수
1번 지표 라이언형(R) 0 튜브형(T) 3
2번 지표 콘형(C) 1 프로도형(F) 0
3번 지표 제이지형(J) 0 무지형(M) 2
4번 지표 어피치형(A) 1 네오형(N) 1

각 지표에서 더 점수가 높은 T,C,M이 성격 유형입니다.
하지만, 4번 지표는 1점으로 동일한 점수입니다. 따라서, 4번 지표의 성격 유형은 사전순으로 빠른 A입니다.

따라서 "TCMA"를 return 해야 합니다.

입출력 예 #2

1번부터 3번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

지표 번호성격 유형점수성격 유형점수
1번 지표 라이언형(R) 6 튜브형(T) 1
2번 지표 콘형(C) 0 프로도형(F) 0
3번 지표 제이지형(J) 0 무지형(M) 0
4번 지표 어피치형(A) 0 네오형(N) 0

1번 지표는 튜브형(T)보다 라이언형(R)의 점수가 더 높습니다. 따라서 첫 번째 지표의 성격 유형은 R입니다.
하지만, 2, 3, 4번 지표는 모두 0점으로 동일한 점수입니다. 따라서 2, 3, 4번 지표의 성격 유형은 사전순으로 빠른 C, J, A입니다.

따라서 "RCJA"를 return 해야 합니다.

 

Survey속에 애초에 검사유형이 주어지지 않는 경우를 생각해야하므로

StringBuilder을 통해 문자들을 합쳐줄때 getOrDefault를 사용해주어야한다.

import java.util.*;
class Solution {
    public String solution(String[] survey, int[] choices) {       
        Map<Character, Integer> map = new HashMap<>();
        
        //유형별 점수 계산
        for(int i=0; i<choices.length; i++){
            if(choices[i] <4){
                char ch = survey[i].charAt(0);
                map.put(ch, map.getOrDefault(ch, 0) + Math.abs(choices[i]-4));
            }
            else if(choices[i] >4){
                char ch = survey[i].charAt(1);
                map.put(ch, map.getOrDefault(ch, 0) + Math.abs(choices[i]-4));
            }
        }
        
        return new StringBuilder()
            .append(map.getOrDefault('R',0) >= map.getOrDefault('T',0) ? 'R':'T')
            .append(map.getOrDefault('C',0) >= map.getOrDefault('F',0) ? 'C':'F')
            .append(map.getOrDefault('J',0) >= map.getOrDefault('M',0) ? 'J':'M')
            .append(map.getOrDefault('A',0) >= map.getOrDefault('N',0) ? 'A':'N')
            .toString();
    }
}

getOrDefault

 찾는 키가 존재한다면 찾는 키의 값을 반환하고 없다면 기본 값을 반환

 

getOrDefault(Object key, V DefaultValue)

매개 변수

  • key : 값을 가져와야 하는 요소의 키입니다.
  • defaultValue : 지정된 키로 매핑된 값이 없는 경우 반환되어야 하는 기본값입니다.

반환 값 : 찾는 key가 존재하면 해당 key에 매핑되어 있는 값을 반환하고, 그렇지 않으면 디폴트 값이 반환됩니다.

 

HashMap의 경우 동일 키 값을 추가할 경우 Value의 값이 덮어쓰기가 됩니다. 따라서 기존 key 값의 value를 계속 사용하고 싶을 경우 getOrDefault 메서드를 사용한다.

더보기

사진들을 보며 추억에 젖어 있던 루는 사진별로 추억 점수를 매길려고 합니다. 사진 속에 나오는 인물의 그리움 점수를 모두 합산한 값이 해당 사진의 추억 점수가 됩니다. 예를 들어 사진 속 인물의 이름이 ["may", "kein", "kain"]이고 각 인물의 그리움 점수가 [5점, 10점, 1점]일 때 해당 사진의 추억 점수는 16(5 + 10 + 1)점이 됩니다. 다른 사진 속 인물의 이름이 ["kali", "mari", "don", "tony"]이고 ["kali", "mari", "don"]의 그리움 점수가 각각 [11점, 1점, 55점]]이고, "tony"는 그리움 점수가 없을 때, 이 사진의 추억 점수는 3명의 그리움 점수를 합한 67(11 + 1 + 55)점입니다.

그리워하는 사람의 이름을 담은 문자열 배열 name, 각 사람별 그리움 점수를 담은 정수 배열 yearning, 각 사진에 찍힌 인물의 이름을 담은 이차원 문자열 배열 photo가 매개변수로 주어질 때, 사진들의 추억 점수를 photo에 주어진 순서대로 배열에 담아 return하는 solution 함수를 완성해주세요.


제한사항

  • 3 ≤ name의 길이 = yearning의 길이≤ 100
    • 3 ≤ name의 원소의 길이 ≤ 7
    • name의 원소들은 알파벳 소문자로만 이루어져 있습니다.
    • name에는 중복된 값이 들어가지 않습니다.
    • 1 ≤ yearning[i] ≤ 100
    • yearning[i]는 i번째 사람의 그리움 점수입니다.
  • 3 ≤ photo의 길이 ≤ 100
    • 1 ≤ photo[i]의 길이 ≤ 100
    • 3 ≤ photo[i]의 원소(문자열)의 길이 ≤ 7
    • photo[i]의 원소들은 알파벳 소문자로만 이루어져 있습니다.
    • photo[i]의 원소들은 중복된 값이 들어가지 않습니다.

입출력 예

nameyearningphotoresult
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may", "kein", "kain", "radi"],["may", "kein", "brin", "deny"], ["kon", "kain", "may", "coni"]] [19, 15, 6]
["kali", "mari", "don"] [11, 1, 55] [["kali", "mari", "don"], ["pony", "tom", "teddy"], ["con", "mona", "don"]] [67, 0, 55]
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may"],["kein", "deny", "may"], ["kon", "coni"]] [5, 15, 0]

입출력 예 설명

입출력 예 #1

첫 번째 사진 속 "may", "kein", "kain", "radi"의 그리움 점수를 합치면 19(5 + 10 + 1 + 3)점 입니다. 두 번째 사진 속 그리워하는 사람들인 "may"와 "kein"의 그리움 점수를 합치면 15(5 + 10)점입니다. 세 번째 사진의 경우 "kain"과 "may"만 그리워하므로 둘의 그리움 점수를 합한 6(1 + 5)점이 사진의 추억 점수입니다. 따라서 [19, 15, 6]을 반환합니다.

입출력 예 #2

첫 번째 사진 속 그리워하는 사람들인 "kali", "mari", "don"의 그리움 점수를 합치면 67(11 + 1 + 55)점입니다. 두 번째 사진 속엔 그리워하는 인물이 없으므로 0점입니다. 세 번째 사진 속 그리워하는 사람은 "don"만 있으므로 55점입니다. 따라서 [67, 0, 55]를 반환합니다.

 

간단한 문제이다 

 

2차원 배열에서 더해줄 점수가 있는 사람만 골라내서 총점을 계산해준 뒤 해당순번의 결과배열에 넣어주는 방법으로 해결하였다.

import java.util.*;
class Solution {
    public int[] solution(String[] name, int[] yearning, String[][] photo) {
        int[] answer = new int[photo.length];
        
        HashMap<String, Integer> scoreMap = new HashMap<>();
        
        for(int i=0; i<name.length; i++){ //이름과 점수를 한쌍으로 묶기
            scoreMap.put(name[i], yearning[i]);
        }
        
        for(int i=0; i<photo.length; i++){
            int score = 0;
            
            for(int j=0; j<photo[i].length; j++){
                if(scoreMap.containsKey(photo[i][j])){ //점수가 있는 사람을 찾아서
                    score += scoreMap.get(photo[i][j]); //해당점수를 스코어에 더해준다
                }
            }
            answer[i] = score;
        }
        return answer;
    }
}
더보기

고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다.

예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다.
당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다.

모든 달은 28일까지 있다고 가정합니다.

다음은 오늘 날짜가 2022.05.19일 때의 예시입니다.

약관 종류유효기간
A 6 달
B 12 달
C 3 달
번호개인정보 수집 일자약관 종류
1 2021.05.02 A
2 2021.07.01 B
3 2022.02.19 C
4 2022.02.20 C
  • 첫 번째 개인정보는 A약관에 의해 2021년 11월 1일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 두 번째 개인정보는 B약관에 의해 2022년 6월 28일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.
  • 세 번째 개인정보는 C약관에 의해 2022년 5월 18일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 네 번째 개인정보는 C약관에 의해 2022년 5월 19일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.

따라서 파기해야 할 개인정보 번호는 [1, 3]입니다.

오늘 날짜를 의미하는 문자열 today, 약관의 유효기간을 담은 1차원 문자열 배열 terms와 수집된 개인정보의 정보를 담은 1차원 문자열 배열 privacies가 매개변수로 주어집니다. 이때 파기해야 할 개인정보의 번호를 오름차순으로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.


제한사항

  • today는 "YYYY.MM.DD" 형태로 오늘 날짜를 나타냅니다.
  • 1 ≤ terms의 길이 ≤ 20
    • terms의 원소는 "약관 종류 유효기간" 형태의 약관 종류와 유효기간을 공백 하나로 구분한 문자열입니다.
    • 약관 종류는 A~Z중 알파벳 대문자 하나이며, terms 배열에서 약관 종류는 중복되지 않습니다.
    • 유효기간은 개인정보를 보관할 수 있는 달 수를 나타내는 정수이며, 1 이상 100 이하입니다.
  • 1 ≤ privacies의 길이 ≤ 100
    • privacies[i]는 i+1번 개인정보의 수집 일자와 약관 종류를 나타냅니다.
    • privacies의 원소는 "날짜 약관 종류" 형태의 날짜와 약관 종류를 공백 하나로 구분한 문자열입니다.
    • 날짜는 "YYYY.MM.DD" 형태의 개인정보가 수집된 날짜를 나타내며, today 이전의 날짜만 주어집니다.
    • privacies의 약관 종류는 항상 terms에 나타난 약관 종류만 주어집니다.
  • today와 privacies에 등장하는 날짜의 YYYY는 연도, MM은 월, DD는 일을 나타내며 점(.) 하나로 구분되어 있습니다.
    • 2000 ≤ YYYY ≤ 2022
    • 1 ≤ MM ≤ 12
    • MM이 한 자릿수인 경우 앞에 0이 붙습니다.
    • 1 ≤ DD ≤ 28
    • DD가 한 자릿수인 경우 앞에 0이 붙습니다.
  • 파기해야 할 개인정보가 하나 이상 존재하는 입력만 주어집니다.

입출력 예

todaytermsprivaciesresult
"2022.05.19" ["A 6", "B 12", "C 3"] ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"] [1, 3]
"2020.01.01" ["Z 3", "D 5"] ["2019.01.01 D", "2019.11.15 Z", "2019.08.02 D", "2019.07.01 D", "2018.12.28 Z"] [1, 4, 5]

입출력 예 설명

입출력 예 #1

  • 문제 예시와 같습니다.

입출력 예 #2

약관 종류유효기간
Z 3 달
D 5 달
번호개인정보 수집 일자약관 종류
1 2019.01.01 D
2 2019.11.15 Z
3 2019.08.02 D
4 2019.07.01 D
5 2018.12.28 Z

오늘 날짜는 2020년 1월 1일입니다.

  • 첫 번째 개인정보는 D약관에 의해 2019년 5월 28일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 두 번째 개인정보는 Z약관에 의해 2020년 2월 14일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.
  • 세 번째 개인정보는 D약관에 의해 2020년 1월 1일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.
  • 네 번째 개인정보는 D약관에 의해 2019년 11월 28일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 다섯 번째 개인정보는 Z약관에 의해 2019년 3월 27일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.

1. 1차원 배열형태로 한꺼번에 들어오는 데이터들을 파싱해준다.

2. 년월일로 되어있는 형태를 일수 단위의 형태로 변경해서 비교하기 편하게 바꿔주는 메서드를 생성한다. 

3. 약관 종류와 유효기간을 HashMap형태로 담아준다.

4. 개인정보 배열을 돌면서 현재날짜와 비교하고 파기에 해당하는 회원인덱스를  Arraylist형태로 저장해준다.

import java.util.*;
class Solution {
    public int[] solution(String today, String[] terms, String[] privacies) {
        
        HashMap<String, Integer> termsMap = new HashMap<>();
        ArrayList<Integer> list = new ArrayList<>();
        
        int todays = getdays(today); //오늘날짜
        
        //terms
        for(String term : terms){ // 약관 종류를 HashMap형태로 저장 <종류, 유효기한>
            String[] temp = term.split(" ");
            termsMap.put(temp[0], Integer.parseInt(temp[1])*28);
        }
        
        //privacies
        for(int i=0; i<privacies.length; i++){
            String[] temp = privacies[i].split(" ");
            int pdays = getdays(temp[0]);
            if(todays >= pdays+termsMap.get(temp[1])){ //파기기한 필터링
            list.add(i+1);
            }
        }
        
        // list -> array
        int[] answer = new int[list.size()];
        for(int i=0; i<list.size(); i++){
            answer[i] = list.get(i);
        }
        return answer;
    }
    
    //연월일 -> 일수로 환산
    public int getdays(String date){
        // String[] temp = date.split(".");
        // int year =  Integer.parseInt(temp[0]);
        // int month =  Integer.parseInt(temp[1]);
        // int day =  Integer.parseInt(temp[2]);
        // return ((year-1)*12*28) + (month-1)*28 + day;
        StringTokenizer st = new StringTokenizer(date,".");
        int year = Integer.parseInt(st.nextToken());
        int month = Integer.parseInt(st.nextToken());
        int day = Integer.parseInt(st.nextToken());
        int days = year*12*28 + month*28 + day;
        return days;
    }
}

split으로 구현한 메서드는 어떤 이유에서인지 범위초가 에러가 난다.

StringTokenizer 와 String.split()의 차이점에 대해 알아봐야 할것 같다.

 

-- 추가

.은 정규식에서 무작위의 한 글자를 의미한다.

split 안의 파라미터는 정규식이기 때문에 다음과 같은 형태로 실행해야 한다.

String[] date = today.split("\\.");

문제 설명

더보기

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
    • 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

유저 ID유저가 신고한 ID설명
"muzi" "frodo" "muzi"가 "frodo"를 신고했습니다.
"apeach" "frodo" "apeach"가 "frodo"를 신고했습니다.
"frodo" "neo" "frodo"가 "neo"를 신고했습니다.
"muzi" "neo" "muzi"가 "neo"를 신고했습니다.
"apeach" "muzi" "apeach"가 "muzi"를 신고했습니다.

각 유저별로 신고당한 횟수는 다음과 같습니다.

유저 ID신고당한 횟수
"muzi" 1
"frodo" 2
"apeach" 0
"neo" 2

위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.

유저 ID유저가 신고한 ID정지된 ID
"muzi" ["frodo", "neo"] ["frodo", "neo"]
"frodo" ["neo"] ["neo"]
"apeach" ["muzi", "frodo"] ["frodo"]
"neo" 없음 없음

따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.

이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.


제한사항

  • 2 ≤ id_list의 길이 ≤ 1,000
    • 1 ≤ id_list의 원소 길이 ≤ 10
    • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
    • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
    • 3 ≤ report의 원소 길이 ≤ 21
    • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
    • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
    • id는 알파벳 소문자로만 이루어져 있습니다.
    • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
    • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.

입출력 예

id_listreportkresult
["muzi", "frodo", "apeach", "neo"] ["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"] 2 [2,1,1,0]
["con", "ryan"] ["ryan con", "ryan con", "ryan con", "ryan con"] 3 [0,0]

입출력 예 설명

입출력 예 #1

문제의 예시와 같습니다.

입출력 예 #2

"ryan"이 "con"을 4번 신고했으나, 주어진 조건에 따라 한 유저가 같은 유저를 여러 번 신고한 경우는 신고 횟수 1회로 처리합니다. 따라서 "con"은 1회 신고당했습니다. 3번 이상 신고당한 이용자는 없으며, "con"과 "ryan"은 결과 메일을 받지 않습니다. 따라서 [0, 0]을 return 합니다.


제한시간 안내

  • 정확성 테스트 : 10초

 

신고당한사람과 신고자의 목록 HashMap

중복제거 HashSet

 

 

문제풀이

import java.util.*;
class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        // 모든 사용자 정보가 id_list에 존재
        // 0. 사용자별 신고당한 자료 필요 초기화 -> reported[user] = 0;  -> map
        // 1. report를 순회하면서 아래 작업을 수행
        // 1-0 신고자와 신고당한자를 구분 : src, dst (string.split(" "))
        // 1-1. 각 사용자별 신고한 사람을 기록 : reporter[src] = Set("dst1", "dst2")
        // 1.2 각 사용자별로 신고당한 횟수를 기록 : reported[dst] = reported[dst] + 1
        // 1.2.1 이때 동일한 사람에게 신고한 경우 횟수를 업데이트 하지 않는다(if)
        // 2. reported를 순회하면서 k이상인 사람을 filter한다 : banned
        // 3. reporter를 순회하면서 banned에 포함된 사람이 있는지 확인한다. answer[i]++
        int[] answer = new int [id_list.length]; //결과값
        Map<String, Integer> userEmail = new HashMap<>(); // 신고당한 자료
        Map<String, HashSet<String>> reporter = new HashMap<>(); //신고자와 신고인원목록
        
        for(int i=0; i<id_list.length; i++){ //초기화
            userEmail.put(id_list[i], 0);
            reporter.put(id_list[i], new HashSet<>());
        }
        
        //신고된 사람의 신고자 목록
        for(String findReport : report){
            String[] temp = findReport.split(" ");
            reporter.get(temp[1]).add(temp[0]); //신고자를 찾아 신고한사람을 넣어줌
        }
        
        //신고된 사람들에 대한 신고자 목록을 HashSet형태(중복방지)로 만들어줌
        for(String reportId : reporter.keySet()){
            HashSet<String> reportedUser = reporter.get(reportId);
            
            if(reportedUser.size()>=k){ //k번 이상 신고당하면 메일을 보내줌
                for(String userSendEmail : reportedUser){
                    userEmail.put(userSendEmail, userEmail.get(userSendEmail)+1);
                }
            }
        }
        
        //신고 피드백 메일 내역 해시맵을 배열화
        for(int i=0; i<id_list.length; i++){
            answer[i] = userEmail.get(id_list[i]);
        }
        return answer;
    }
}

 

신고된 사람과 그에대한 신고자 목록을 HashMap으로 만들어준 후 중복을 방지하기 위해 HashSet을 사용하여 한번 더 필터링 해준 뒤 신고 수 기준 k에 맞게 if문으로 걸러주면 된다.

문제 설명
얀에서는 매년 달리기 경주가 열립니다. 해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부릅니다. 예를 들어 1등부터 3등까지 "mumu", "soe", "poe" 선수들이 순서대로 달리고 있을 때, 해설진이 "soe"선수를 불렀다면 2등인 "soe" 선수가 1등인 "mumu" 선수를 추월했다는 것입니다. 즉 "soe" 선수가 1등, "mumu" 선수가 2등으로 바뀝니다.

선수들의 이름이 1등부터 현재 등수 순서대로 담긴 문자열 배열 players와 해설진이 부른 이름을 담은 문자열 배열 callings가 매개변수로 주어질 때, 경주가 끝났을 때 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return 하는 solution 함수를 완성해주세요.

제한사항
5 ≤ players의 길이 ≤ 50,000
players[i]는 i번째 선수의 이름을 의미합니다.
players의 원소들은 알파벳 소문자로만 이루어져 있습니다.
players에는 중복된 값이 들어가 있지 않습니다.
3 ≤ players[i]의 길이 ≤ 10
2 ≤ callings의 길이 ≤ 1,000,000
callings는 players의 원소들로만 이루어져 있습니다.
경주 진행중 1등인 선수의 이름은 불리지 않습니다.
입출력 예
players callings result
["mumu", "soe", "poe", "kai", "mine"] ["kai", "kai", "mine", "mine"] ["mumu", "kai", "mine", "soe", "poe"]
입출력 예 설명
입출력 예 #1

4등인 "kai" 선수가 2번 추월하여 2등이 되고 앞서 3등, 2등인 "poe", "soe" 선수는 4등, 3등이 됩니다. 5등인 "mine" 선수가 2번 추월하여 4등, 3등인 "poe", "soe" 선수가 5등, 4등이 되고 경주가 끝납니다. 1등부터 배열에 담으면 ["mumu", "kai", "mine", "soe", "poe"]이 됩니다.

 

 

많은 양의 데이터를 검색하는데 뛰어난 성능을 가진 HashMap을 사용할 수 있는지에 대한 문제인 것 같다

HashMap의 Key에는 String, Value에는 인덱스형태로 지정하여 get을 사용해서 일치하는 단어에 대한 해당 인덱스를 반환 할 수 있도록 하였다.

import java.util.*;
public class Solution {
    public String[] solution(String[] players, String[] callings) {
        String [] answer = players; // 얕은복사
        HashMap<String, Integer> indexMap = new HashMap<>();

        for (int i = 0; i < players.length; i++) {
            indexMap.put(players[i], i);
        }

        for (String calling : callings) {
            int idx = indexMap.get(calling);
            
            answer[idx] = answer[idx-1];
            answer[idx-1] = calling;
            
            indexMap.put(answer[idx - 1], idx - 1);
            indexMap.put(answer[idx], idx);
        }
        return answer; //players도 동일
    }
}

결과 배열에 값을 스왑 한 뒤 그에 맞게 해시맵을 업데이트 해줘야한다.

 

return 값에 player을 하던 answer을 하던 같은 결과값이 나와 확인해 보니 깊은복사 / 얕은복사에 관련된 문제였다.

String [] answer = Arrays.copyOf(players, players.length); // 깊은복사

 

 

players를 그대로 변경하는 방법

 

import java.util.*;
public class Solution {
    public String[] solution(String[] players, String[] callings) {
        HashMap<String, Integer> indexMap = new HashMap<>();

        for (int i = 0; i < players.length; i++) {
            indexMap.put(players[i], i);
        }

        for (String calling : callings) {
            int idx = indexMap.get(calling);
            
            players[idx] = players[idx-1];
            players[idx-1] = calling;
            
            indexMap.put(players[idx - 1], idx - 1);
            indexMap.put(players[idx], idx);
        }
        return players;
    }
}
// ------------------------- 리스트 스트림

list.stream().
distinct() - 중복되는 요소 모두 제거하고 새로운 스트림 반환
sorted() - 정렬
filter(m-> m.startsWith("시작문자열")) - 해당글자로 시작하면 true 아니면 false  
toArray(String[]::new) - 배열생성
.getAsInt() - Integer로 형변환

// --------------------------배열 스트림

Arrays.stream(arr).
mapToInt(m-> m.length()) - 배열 문자열의 길이 출력 
max() - 최대값


//------------------------ 스트림 클래스

Stream.concat(list1.stream(), list2.stream()) - 리스트1과 리스트2 합치기
.collect(Collectors.toList()) - 리스트 형식으로 변환

* Arrays.copyOf(기존배열, 지정할 크기) - 배열크기 재지정

 

* Arrays.copyOfRange(배열, 시작위치, 끝위치) - 배열 시작위치 ~ 끝위치까지 복사

import java.util.Arrays; 

 

* System.arraycopy 는 byte[] 형태의 데이터를 자르거나 연접하기 위해 사용하는 메소드 입니다.

 

System.arraycopy (src, srcPos, dest, destPos, length)

 

Object src  : 원본 배열

int srcPos  : 원본 배열의 복사시작 위치, 처음부터 데이터를 읽어올거면 0 을 넣어줍니다.

Object dest : 복사할 배열, 복사하려는 대상입니다. -> 이곳에 복사됌

int destPos : 복사할 배열의 복사 시작 위치, 처음부터 데이터를 쓸 거면 0 을 넣어줍니다.

int length : 복사할 요소의 개수

public class Solution { 
	public int[] addToFront(int[] arr, int el) {
    // TODO:
		int [] result = new int[arr.length+1];
		result[0] = el;
		System.arraycopy(arr, 0, result, 1, arr.length);
		return result;
	} 
}

 

입출력 예시

int[] output = addToFront(new int[]{1, 2}, 3);
System.out.println(output); // -> [3, 1, 2]

 

위와 같은 방식으로 사용한다. 이 방식의 장점은, 원하는 부분만 복사할 수 있다는 점과 불필요한 인스턴스 생성을 방지하여 메모리 자원 낭비를 예방하고, 더 빠르게 실행된다는 점이다. 가독성 측면에서도 효율적이다.

split 메서드는 입력받은 정규표현식 또는 특정 문자열을 기준으로 배열에 차례대로 저장하여 리턴한다.

 

package com.codestates.coplit; 

public class Solution { 
	public String[] getAllWords(String str) {
    // TODO:
    String [] array = new String [0];
    if(str.length() == 0) return array;
    array = str.split(" ");
    return array;
  } 
}

입출력 예시

String[] output = getAllWords("Radagast the Brown");
System.out.println(output); // --> ["Radagast", "the", "Brown"]

 

 

문제 설명

임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단하려 합니다.
n이 양의 정수 x의 제곱이라면 x+1의 제곱을 리턴하고, n이 양의 정수 x의 제곱이 아니라면 -1을 리턴하는 함수를 완성하세요.

제한 사항
  • n은 1이상, 50000000000000 이하인 양의 정수입니다.
입출력 예nreturn
121 144
3 -1
입출력 예 설명

입출력 예#1
121은 양의 정수 11의 제곱이므로, (11+1)를 제곱한 144를 리턴합니다.

입출력 예#2
3은 양의 정수의 제곱이 아니므로, -1을 리턴합니다.

 

해당문제는 Math.sqrt를 통해 제곱근을 구해주고

Math.pow를 통해 제곱을 해주면 간단하게 풀 수 있다.

 

Math.sqrt를 이용해서 제곱근을 구한뒤 해당 제곱근의 제곱이 입력값과 일치한다면 +1에 대한 제곱값을 리턴해준다.

 

class Solution {
    public long solution(long n) {
        long sqrt = (long)Math.sqrt(n);

        if (Math.pow(sqrt, 2) == n) {
            return (long)Math.pow(sqrt + 1, 2);
        } else {
            return -1;
            }
    }
}

 

설정 -> 꾸미기 -> 스킨편집 -> html 편집 -> CSS
 
아무곳에나 아래 코드 추가하면 테두리가 사라진다
 
 
pre {
  border: 0px!important;
  padding : 0px!important;
}
pre code {
  padding : 20px!important;
}

sudo vi /etc/environment 에서  전역변수로 설정된다.

 

export Key=Value 입력

 

적용하려면 재부팅해야한다.

 

- mypassword는 yml에서 환경변수로 읽어오지 못한다는 사실을 아는데 꼬박 6시간이 걸렸다...

my_password로 수정하였다 

원본 repository로부터 최신 정보를 가져와 fork한 repository를 업데이트 시키는 작업이다.

 

동기화 작업이 완료되면 local, remote 저장소가 모두 Origin Repository의 최신 상태에 동기화된다.

 

작업 진행 순서

 

1.$git remote add upstream [원본저장소URL]   <- 부모 레파지토리 연결

 

2. $git remote -v    <- 연결되어있는지 확인

 

3. $git fetch upstream  <- 최신버전으로 업데이트 

- 위 명령어를 통해 원본 Repository에 master branch에 있는 내용들이 본인의 PC에 upstream/master로 복사가 된다.

 

4. $git checkout master

- 이후 master에 가져온 내용을 합치기 위해 먼저 master로 이동해준다.

 

5. $git merge upstream/master

- 명령어를 통해 merge해준다.

 

6. $git push origin master

- git push를 하면 나의 Repository에 원본 Repository의 변경된 사항이 적용

'Study > Git' 카테고리의 다른 글

AWS - RDS 연결 오류 해결, 보안규칙에 내 IP추가하기  (0) 2023.03.19
커밋 되돌리고 서버에 반영하기  (0) 2023.03.15
Git 기초  (0) 2022.11.03

+ Recent posts