
/*
문제 분석
1. 정보
- 1 ~ N번으로 분류된 개인정보 N개가 존재
- 약관 종류는 여러가지가 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있음
- 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야함.
- 모든달은 28일까지 있다고 가정
2. 목표
- 파기해야할 개인정보를 return
3. 제약 조건
- 1 <= 약관의 유효기간 개수 <= 20
- A <= 약관 종류 <= Z
- 1 <= 유효기간 <= 100
- 1 <= 수집된 개인정보 <= 100
- 2000 <= 연 <= 2022
- 1 <= 월 <= 12
- 1 <= 일 <= 28
풀이
1. 아이디어
- 먼저 각 약관의 유효기간을 int[] 배열에 저장함
- privacies를 돌면서 하나씩 비교
- 먼저 공백을 기준으로 분리
- 앞에는 날짜, 뒤에는 약관 종류
- 날짜를 다시 .을 기준으로 분리
- 약관의 유효기간을 월에 더함
- 이때 (유효기간 + 현재 월) / 12를 구해 연에 더해주고
- (유효기간 + 현재 월) % 12 부분에 1을 추가하여 더해줌
- 날짜를 다시 합치고 today와 비교
- today보다 작거나 같다면 파기해야할 대상
- result에 해당 idx 추가
*/
import java.util.*;
class Solution {
public int[] solution(String today, String[] terms, String[] privacies) {
List<Integer> result = new ArrayList<>();
today = today.replaceAll("\\.", "");
int[] valid = new int[26];
for (int i = 0; i < terms.length; i++) {
String[] tmp = terms[i].split(" ");
valid[tmp[0].charAt(0) - 'A'] = Integer.parseInt(tmp[1]);
}
for (int i = 0; i < privacies.length; i++) {
String[] splitYnT = privacies[i].split(" ");
String[] date = splitYnT[0].split("\\.");
date[1] = String.valueOf((Integer.parseInt(date[1]) + valid[splitYnT[1].charAt(0) - 'A']));
if (Integer.parseInt(date[1]) > 12) {
date[0] = String.valueOf(Integer.parseInt(date[0]) + Integer.parseInt(date[1]) / 12);
date[1] = String.valueOf(Integer.parseInt(date[1]) % 12);
}
if (Integer.parseInt(date[1]) == 0) {
date[0] = String.valueOf(Integer.parseInt(date[0]) - 1);
date[1] = "12";
}
String fin = date[0] + String.format("%02d", Integer.parseInt(date[1]))+ date[2];
if (Integer.parseInt(today) >= Integer.parseInt(fin)) {
result.add(i + 1);
}
}
int[] answer = new int[result.size()];
for (int i = 0; i < answer.length; i++) {
answer[i] = result.get(i);
}
Arrays.sort(answer);
return answer;
}
}
/*
문제 분석
1. 정보
- 얀에서는 달리기 경주가 열림
- 해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때, 추월한 선수의 이름을 부름
- 예를 들어,
- 1 : 무무, 2 : 소, 3 : 포 일때
- 해설진이 소를 불렀다면, 소가 무무를 추월했다는 뜻
2. 목표
- 해설진들이 부르는 소리를 이용해 최종 등수를 배열에 담아 return
3. 제약 조건
- 5 <= 선수 <= 50000
- 2 <= 해설 길이 <= 1,000,000
풀이
1. 아이디어
- 선수의 콜링이 들을때마다 일일히 선수의 위치를 찾아 바꾼다면 시간초과 가능성 존재
- 따라서 선수의 이름과 현재 등수를 Map 배열에 같이 저장해두어 찾을때 편하게 찾을 수 있도록 함
- 콜링에 해당하는 선수의 현재 등수를 가져오고, 해당 등수 - 1인 선수와 자리를 바꿈
- 마찬가지로 map의 데이터도 수정해줌
- 모든 콜링이 끝나고, player 그대로 return
*/
import java.util.*;
class Solution {
public String[] solution(String[] players, String[] callings) {
Map<String, Integer> map = new HashMap<>();
for (int i = 0; i < players.length; i++) {
map.put(players[i], i);
}
for (String call : callings) {
int callRank = map.get(call);
players[callRank] = players[callRank - 1];
players[callRank - 1] = call;
map.put(players[callRank - 1], callRank - 1);
map.put(players[callRank], callRank);
}
return players;
}
}
/*
문제 분석
1. 정보
- 직사각형 격자모양의 공원이 존재
- O : 지나갈 수 있는 길
- X : 장애물
- 명령은 다음과 같이 주어짐
- ["방향 거리", "방향 거리", ...]
- 만약 해당 명령을 수행할때
- 공원을 벗어나거나
- 장애물에 마주하는 경우
- 해당 명령을 무시하고 다음 명령을 수행
2. 목표
- 시작지점 S에서 시작해서 모든 명령을 수행하고 난 후의 좌표를 출력
3. 제약 조건
- 3 <= 공원 높이 <= 50
- 3 <= 공원 너피 <= 50
- 1 <= 명령 개수 <= 50
- 명령은 OP N으로 구성
- OP : N S W E중 하나
- 1 <= N <= 9
풀이
1. 아이디어
- 구현 문제
- 받은 park 배열에서 S를 찾아 시작지점으로 지정
- 명령을 순서대로 수행
- 해당 명령을 수행할 수 없는 조건이 발생하면
- 다음 명령 수행
- 수행할 수 있다면, 현재 위치 업데이트
- 모든 명령을 수행한 후 결과 좌표 return
*/
class Solution {
public int[] solution(String[] park, String[] routes) {
int[] answer = findStart(park);
int H = park.length;
int W = park[0].length();
for (int i = 0; i < routes.length; i++) {
char dir = routes[i].charAt(0);
int len = routes[i].charAt(2) - '0';
if (isAvailable(park, answer, dir, len, H, W)) {
switch(dir){
case 'N' -> answer[0] -= len;
case 'S' -> answer[0] += len;
case 'W' -> answer[1] -= len;
case 'E' -> answer[1] += len;
}
}
}
return answer;
}
public boolean isAvailable(String[] park, int[] cur, char dir, int len, int H, int W) {
int[] tmp = cur.clone();
for (int i = 0; i < len; i++) {
switch(dir){
case 'N' -> tmp[0]--;
case 'S' -> tmp[0]++;
case 'W' -> tmp[1]--;
case 'E' -> tmp[1]++;
}
if (tmp[0] < 0 || tmp[0] >= H || tmp[1] < 0 || tmp[1] >= W) {
return false;
}
if(park[tmp[0]].charAt(tmp[1]) == 'X'){
return false;
}
}
return true;
}
public int[] findStart(String[] park){
int[] start = new int[2];
for (int i = 0; i < park.length; i++) {
for (int j = 0; j < park[i].length(); j++) {
if (park[i].charAt(j) == 'S') {
start[0] = i;
start[1] = j;
return start;
}
}
}
return start;
}
}
/*
문제 분석
1. 정보
- 무지가 개발하려는 시스템은 다음과 같음
- 각 유저는 한 번에 한 명의 유저를 신고 가능
- 신고 횟수에 제한은 없음. 서로 다른 유저를 계속 신고 가능
- 한 유저를 여러번 신고할 수도 있지만, 동일한 유저에 대한 신고는 1회로 처리
- k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송
- 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송
2. 목표
- 각 유저가 받는 메일의 개수를 배열로 return
3. 제약 조건
- 2 <= 유저의 수 <= 1000
- 1 <= 신고 횟수 <= 200000
- 1 <= k <= 200
풀이
1. 아이디어
- 먼저 id_list를 활용하여 Map<String, Integer> userId를 만들어 Id를 저장
- 또한, boolean[][] check 배열을 만들어 i 유저가 j 유저에게 신고당했는지 저장
- report를 모두 탐색
- 해당 report에서 왼쪽은 신고한사람, 오른쪽은 신고를 당한 사람
- 따라서 userId에서 왼쪽과 오른쪽의 id값을 찾아 check[j][i] = true;
- 모든 report가 끝났다면,
- check 배열을 순회
- 만약 i번째 사람이 신고당한 횟수가 k 이상이면 다시 돌면서 신고 한사람들의 answer에 1씩 추가
- 이후 answer return
*/
import java.util.*;
class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
Map<String, Integer> users = new HashMap<>();
for (int i = 0; i < id_list.length; i++) {
users.put(id_list[i], i);
}
int[] answer = new int[id_list.length];
boolean[][] check = new boolean[id_list.length][id_list.length];
for (int i = 0; i < report.length; i++) {
String[] su = report[i].split(" ");
int left = users.get(su[0]);
int right = users.get(su[1]);
check[right][left] = true;
}
for (int i = 0; i < check.length; i++) {
int sum = 0;
for (int j = 0; j < check[i].length; j++) {
if (check[i][j]) {
sum++;
}
}
if (sum >= k) {
for (int j = 0; j < check[i].length; j++) {
if (check[i][j]) {
answer[j]++;
}
}
}
}
return answer;
}
}
/*
문제 분석
1. 정보
- 문자열 S에는 공백으로 구분된 숫자들이 저장되어 있음
2. 목표
- S에 나타나는 숫자중 최솟값과 최댓값을 찾아 반환
3. 제약 조건
- S에는 둘 이상의 정수가 공백으로 구분
풀이
1. 아이디어
- S문자열을 split을 사용해 공백을 기준으로 나눔
- 최솟값과 최댓값을 저장하기 위한 integer 선언
- 나눠진 문자열들을 순회
- 해당 문자열을 Integer로 바꾼 뒤
- 최솟값보다 작다면 최솟값 업데이트
- 최댓값보다 크다면 최댓값 업데이트
- min + " " + max로 return
*/
class Solution {
public String solution(String s) {
String[] split = s.split(" ");
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (String cur : split) {
int curNum = Integer.parseInt(cur);
min = Math.min(min, curNum);
max = Math.max(max, curNum);
}
String answer = min + " " + max;
return answer;
}
}