프로그래머스LV1_4

개발자를 꿈꾸는 뚱이·2026년 3월 18일

코딩테스트 스터디

목록 보기
21/39

체크사항

문제를 정답률 높은 순으로 풀어서 지금 거의 뒷쪽이라 정답률이 낮은 문제들을 풀고 있는데 LV1이지만 쉽지 않은 문제들이 많았다. LV1 마무리 하면 이모지로 표시해둔 문제만 다시 풀어봐야겠다.


  • 둘 만의 암호
    class Solution {
        public String solution(String s, String skip, int index) {
            StringBuilder sb = new StringBuilder();
            for(char c : s.toCharArray()) {
                int plus = 0;
                while(plus < index) {
                    c++;
                    if(c > 'z') {
                        c = 'a';
                    }
                    if(!skip.contains(String.valueOf(c))) {
                        plus++;
                    }
                }
                sb.append(c);
            }
            return sb.toString();
        }
    }
한글자씩 포함되는지 판단하여 스킵을 시뮬레이션 식으로 해결
  • 이웃한 칸
    class Solution {
        public int solution(String[][] board, int h, int w) {
            int answer = 0;
            String color = board[h][w];
            int[] dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
            for(int i = 0; i < 4; i++){
                int nx = w + dx[i];
                int ny = h + dy[i];
                if(nx < 0 || nx >= board[0].length || ny < 0 || ny >= board.length) continue;
                if(board[ny][nx].equals(color)) answer++;
            }
            return answer;
        }
    }
상하좌우를 해당 좌표를 넘어가는지 체크하여 색깔이 같은 개수를 세면 해결
  • 문자열 나누기
    class Solution {
        public int solution(String s) {
            int answer = 0;
            int same = 0, another = 0;
            char cur = ' ';
            for(char c : s.toCharArray()){
                if(same == 0){
                    cur = c;
                    same++;
                }
                else if(c == cur){
                    same++;
                }
                else if(c != cur){
                    another++;
                }
                if(same == another){
                    answer++;
                    same = 0;
                    another = 0;
                    cur = ' ';
                }
            }
            if(cur != ' ') answer++;
            return answer;
        }
    }
처음 나누기 시작한 글이면 cur에 넣고 같은 개수를 늘리고 처음이 아니라면 cur과 비교 후 same, another에 각각 넣어 같아지면 횟수를 늘리고 cur, same, another를 초기화하고 마지막에 cur이 남아있다면 횟수를 늘려 해결
  • 대충 만든 자판
    import java.util.*;
    
    class Solution {
        public int[] solution(String[] keymap, String[] targets) {
            int[] answer = new int[targets.length];
            Map<Character, Integer> m = new HashMap<>(); 
            for(String key : keymap){
                for(int i = 0; i < key.length(); i++){
                    char c = key.charAt(i);
                    m.put(c, Math.min(m.getOrDefault(c, 101), i + 1)); 
                }
            }
            for(int i = 0; i < targets.length; i++){
                for(int j = 0; j < targets[i].length(); j++){
                    char c = targets[i].charAt(j);
                    
                    if(!m.containsKey(c)){
                        answer[i] = -1;
                        break;
                    }
                    answer[i] += m.get(c);
                }
            }
            return answer;
        }
    }
모든 원소를 체크하면서 해결하려면 반복문이 3개가 필요해 이는 시간 초과가 날 것 같아서 맵을 활용하였다. 맵에 해당 글자를 누르는 최솟값으로 유지하여 targets의 단어를 돌면서 존재하지 않으면 -1로 하고 있다면 누적하는 방식으로 해결
  • 다트 게임 🤔
    class Solution {
        public int solution(String dartResult) {
            int answer = 0;
            int cur = 0, prev = -101, idx = 0;
            char b = ' ', op = ' ';
            char[] ch = dartResult.toCharArray();
            while(idx < ch.length){
                char c = ch[idx];
                if(Character.isDigit(c)){
                    int i = c - '0';
                    if(i == 1 && idx + 1 < ch.length && ch[idx + 1] == '0'){
                        cur = 10;
                        idx += 2;
                    }
                    else{
                        cur = i;
                        idx++;
                    }
                }
                else{
                    if(c == 'S' || c == 'D' || c == 'T'){
                        b = c;
                        int plus = Score(cur, b);
                        if(idx + 1 < ch.length && (ch[idx + 1] == '*' || ch[idx + 1] == '#')){
                            op = ch[idx + 1];
                            idx += 2;
                            if(op == '*'){
                                plus *= 2;
                                if(prev != -101){
                                    answer += prev;
                                }
                            }
                            else plus *= -1;
                        }
                        else{
                            idx++;
                        }
                        prev = plus;
                        answer += plus;
                    }
                }
            }
            return answer;
        }
        
        private int Score(int s, char b){
            int r = 0;
            switch(b){
                case 'S':
                    r += s;
                    break;
                case 'D':
                    r += Math.pow(s, 2);
                    break;
                case 'T':
                    r += Math.pow(s, 3);
                    break;
            }
            return r;
        }
    }
    
    // 개선
    class Solution {
        public int solution(String dartResult) {
            int[] score = new int[3]; 
            int round = -1;
            char[] ch = dartResult.toCharArray();
            for(int i = 0; i < ch.length; i++){
                char c = ch[i];
                if(Character.isDigit(c)){
                    round++;
                    if(c == '1' && ch[i + 1] == '0'){
                        score[round] = 10;
                        i++;
                    } else {
                        score[round] = c - '0';
                    }
                }
                else if(c == 'S' || c == 'D' || c == 'T'){
                    if(c == 'D') score[round] = (int)Math.pow(score[round], 2);
                    else if(c == 'T') score[round] = (int)Math.pow(score[round], 3);
                }
                else if(c == '*'){
                    score[round] *= 2;
                    if(round > 0) {
                        score[round - 1] *= 2;
                    }
                } 
                else if(c == '#'){
                    score[round] *= -1;
                }
            }
            return score[0] + score[1] + score[2];
        }
    }
다트 결과 전체를 순회하면서 점수, 보너스, 옵션 여부에 따른 처리를 했는데 idx를 while문 안에서 관리를 해서 인덱스 범위가 터질 수 있고 현재 코드에 분기 처리가 많아 좀 헷갈리는 부분이 많아 코드를 개선해보았다.(AI 도움 받음) 3번 던지는 것으로 고정이기에 라운드 별로 관리하는 것으로 개선하였다.
  • 로또의 최고 순위와 최저 순위
    class Solution {
        public int[] solution(int[] lottos, int[] win_nums) {
            int[] rank = {6, 6, 5, 4, 3, 2, 1}; 
            int zero = 0, cnt = 0;
            for(int num : lottos){
                if(num == 0){
                    zero++;
                    continue;
                }
                for(int win : win_nums){
                    if(num == win){
                        cnt++;
                        break;
                    }
                }
            }
            return new int[]{rank[cnt + zero], rank[cnt]};
        }
    }
지워진 번호 개수와 로또 당첨 번호와 맞는 개수를 세어 지워진 번호가 다 맞으면 가장 높은 순위이고 다 틀리면 가장 낮은 순위인 것으로 순위를 넣으면 해결
  • 체육복 🤔
    class Solution {
    
        public int solution(int n, int[] lost, int[] reserve) {
    
            int answer = n - lost.length;
    
            for(int lo : lost){
    
                for(int i = 0; i < reserve.length; i++){
    
                    if(reserve[i] == lo || reserve[i] == lo - 1 || reserve[i] == lo + 1){
    
                        reserve[i] = -1;
    
                        answer++;
    
                        break;
    
                    }
    
                }
    
            }
    
            return answer;
    
        }
    
    }
    
    import java.util.*;
    
    class Solution {
        public int solution(int n, int[] lost, int[] reserve) {
            int answer = n - lost.length;
            Arrays.sort(lost);
            Arrays.sort(reserve);
            for (int i = 0; i < lost.length; i++) {
    			for (int j = 0; j < reserve.length; j++) {
    				if (lost[i] == reserve[j]) {
    					answer++;
    					lost[i] = -1;
    					reserve[j] = -1;
                        break;
    				}
    			}
    		}
            for (int i = 0; i < lost.length; i++) {
                if(lost[i] == -1) continue;
    			for (int j = 0; j < reserve.length; j++) {
    				if (lost[i] - 1 == reserve[j] || lost[i] + 1 == reserve[j]) {
    					answer++;
    					reserve[j] = -1;
    					break;
    				}
    			}
    		}
            return answer;
        }
    }
처음에 첫 번째로 풀었는데 틀리길래 다른 사람 풀이를 찾아봤는데 2 배열을 정렬해서 자기거를 가져가고 빌려주는 것을 분리해서 풀이하길래 정렬을 하는 이유가 궁금했다.
정렬을 하는 이유는 반례가 있다. 도난이 [3, 1]이고 여분이 [2, 4]이면 정렬 없이 진행하면 3번은 2번 것을 빌리고 1번은 빌리지 못하는 데 실제로는 1번은 2번을 3번을 4번을 빌리면 모두 빌릴 수 있다. 따라서 정렬을 하면 옳게 빌릴 수 있다. 이를 통해 그리디 원칙을 알았다.
그리디 원칙→왼쪽부터 오른쪽(또는 반대로) 일관된 방향성을 가지고 선택해야 한다.
  • 완주하지 못한 선수
    import java.util.*;
    
    class Solution {
        public String solution(String[] participant, String[] completion) {
            String answer = "";
            Map<String, Integer> m = new HashMap<>();
            for(String com : completion){
                if(m.containsKey(com)){
                    m.put(com, 1 + m.get(com));
                }
                else{
                    m.put(com, 1);
                }
            }
            for(String par : participant){
                if(!m.containsKey(par)){
                    answer = par;
                    break;
                }
                else{
                    int cnt = m.get(par);
                    if(cnt > 1) m.put(par, cnt - 1);
                    else m.remove(par);
                }
            }
            return answer;
        }
    }
완주한 선수를 맵에 담고 참가자를 돌면서 맵에 없다면 답으로 반환
  • 햄버거 만들기 🤔
    import java.util.*;
    
    class Solution {
        public int solution(int[] ingredient) {
            int answer = 0;
            List<Integer> list = new ArrayList<>();
            for(int i : ingredient){
                list.add(i);
                while(list.size() >= 4){
                    int s = list.size();
                    if(list.get(s - 1) != 1 ||
                      list.get(s - 2) != 3 ||
                      list.get(s - 3) != 2 ||
                      list.get(s - 4) != 1) break;
                    for(int j = 0; j < 4; j++){
                        list.remove(list.size() - 1);
                    }
                    answer++;
                }
            }
            return answer;
        }
    }
    
    // 개선
    class Solution {
        public int solution(int[] ingredient) {
            int answer = 0;
            int[] stack = new int[ingredient.length]; 
            int sp = 0;
            for (int i : ingredient) {
                stack[sp] = i;
                sp++;
                if (sp >= 4 && 
                    stack[sp - 1] == 1 &&
                    stack[sp - 2] == 3 &&
                    stack[sp - 3] == 2 &&
                    stack[sp - 4] == 1) {               
                    answer++;
                    sp -= 4; 
                }
            }
            return answer;
        }
    }
처음에 전체를 넣어서 큐나 리스트로 해결하려고 했는데 중간 부분을 지우는 것이 쉽지 않아서 다른 사람 풀이를 봤는데 전체를 한 번에 넣는 것이 아니라 1개씩 넣어가면서 처리하면 가능했다. 또한 2번째 방법으로 스택의 LIFO 규칙을 활용하여 list의 제거나 while 문 없이 좀 더 빠른 속도로 해결이 가능하다.
  • 숫자 짝꿍 🤔
    import java.util.*;
    
    class Solution {
        public String solution(String X, String Y) {
            List<String> li = new ArrayList<>();
            for(char c : X.toCharArray()){
                String s = Character.toString(c);
                if(Y.contains(s)){
                    Y = Y.replaceFirst(s, " ");
                    li.add(s);
                }
            }
            if(li.size() == 0) return "-1";
            Collections.sort(li, Collections.reverseOrder());
            StringBuilder sb = new StringBuilder();
            for(String s : li){
                if(sb.length() == 0 && s.equals("0")) continue;
                sb.append(s);
            }
            if(sb.length() == 0) return "0";
            return sb.toString();
        }
    }
    
    // 개선
    class Solution {
        public String solution(String X, String Y) {
            int[] countX = new int[10];
            int[] countY = new int[10];
            for(char c : X.toCharArray()) countX[c - '0']++;
            for(char c : Y.toCharArray()) countY[c - '0']++;
            StringBuilder sb = new StringBuilder();
            for(int i = 9; i >= 0; i--){
                int common = Math.min(countX[i], countY[i]);
                for(int j = 0; j < common; j++){
                    sb.append(i);
                }
            }
            if(sb.length() == 0) return "-1";
            if(sb.charAt(0) == '0') return "0"; 
            return sb.toString();
        }
    }
처음 방식으로 list에 공통 요소를 넣고 내림차순 정렬하여 붙여서 풀었는데 시간 초과가 나서 다른 사람 풀이를 보면서 개선을 해보았다.
매번 Y를 대체하고 정렬하는 방식이 아니라 각 문자에서 0-9가 나온 횟수를 넣어 최소 개수만큼 9부터 0까지를 붙여서 예외 처리까지 하면 해결된다.
  • 데이터 분석 🤔
    import java.util.*;
    
    class Solution {
        public int[][] solution(int[][] data, String ext, int val_ext, String sort_by) {
            String[] condition = {"code", "date", "maximum", "remain"};
            int idx1 = -1, idx2 = -1;
            for(int i = 0; i < 4; i++){
                if(condition[i].equals(ext)) idx1 = i;
                if(condition[i].equals(sort_by)) idx2 = i;
            }
            List<int[]> li = new ArrayList<>();
            for(int[] d : data){
                if(d[idx1] < val_ext)
                     li.add(d);
            }
            final int sortIdx = idx2;
            li.sort((a, b) -> a[sortIdx] - b[sortIdx]);
            int[][] answer = new int[li.size()][4];
            for(int i = 0; i < li.size(); i++){
                answer[i] = li.get(i);
            }
            return answer;
        }
    }
문제 조건대로 조건 1의 인덱스, 조건 2의 인덱스를 찾아 해당하는 배열만 넣고 람다식으로 정렬을 하여 해결
중간에 조건 2의 인덱스를 적용하여 정렬하기 위해 final 변수를 사용하였는데 이렇게 안하면 람다식 안에서 컴파일 에러가 나서 찾아서 해결하였다.
  • 성격 유형 검사하기
    import java.util.*;
    
    class Solution {
        public String solution(String[] survey, int[] choices) {
            Map<Character, Integer> m = new HashMap<>();
            int[] score = {3, 2, 1, 0, 1, 2, 3};
            for(int i = 0; i < survey.length; i++){
                char[] ch = survey[i].toCharArray();
                if(choices[i] == 4) continue;
                else if(choices[i] < 4){
                    m.put(ch[0], m.getOrDefault(ch[0], 0) + score[choices[i] - 1]);
                }
                else{
                    m.put(ch[1], m.getOrDefault(ch[1], 0) + score[choices[i] - 1]);
                }
            }
            StringBuilder sb = new StringBuilder();
            char[] ch = {'R', 'T', 'C', 'F', 'J', 'M', 'A', 'N'};
            for(int i = 0; i < 8; i += 2){
                if(m.getOrDefault(ch[i], 0) > m.getOrDefault(ch[i + 1], 0)){
                    sb.append(ch[i]);
                }
                else if(m.getOrDefault(ch[i], 0) < m.getOrDefault(ch[i + 1], 0)){
                    sb.append(ch[i + 1]);
                }
                else{
                    char c = ch[i] < ch[i + 1]? ch[i] : ch[i + 1];
                    sb.append(c);
                }
                
            }
            return sb.toString();
        }
    }
점수와 문자를 맵에 저장하여 더 높은 문자를 붙이면 해결
  • 크레인 인형뽑기 게임 🤔
    import java.util.*;
    
    class Solution {
        public int solution(int[][] board, int[] moves) {
            int answer = 0;
            List<Integer>[] li = new ArrayList[board.length];
            for(int i = board[0].length - 1; i >= 0; i--){
                li[i] = new ArrayList<>();
                for(int j = board.length - 1; j >= 0; j--){
                    if(board[j][i] == 0) continue;
                    li[i].add(board[j][i]);
                }
            }
            List<Integer> bucket = new ArrayList<>();
            for(int m : moves){
                if(li[m - 1].size() <= 0) continue;
                int num = li[m - 1].get(li[m - 1].size() - 1);
                li[m - 1].remove(li[m - 1].size() - 1);
                if(bucket.size() > 0 && bucket.get(bucket.size() - 1) == num){
                    answer += 2;
                    bucket.remove(bucket.size() - 1);
                }
                else{
                    bucket.add(num);
                }
            }
            return answer;
        }
    }
    
    // 개선
    import java.util.*;
    
    class Solution {
        public int solution(int[][] board, int[] moves) {
            int answer = 0;
            Stack<Integer> bucket = new Stack<>();
            for (int m : moves) {
                int col = m - 1;
                for (int row = 0; row < board.length; row++) {
                    if (board[row][col] != 0) {
                        int doll = board[row][col];
                        board[row][col] = 0;
                        if (!bucket.isEmpty() && bucket.peek() == doll) {
                            bucket.pop();
                            answer += 2;
                        } else {
                            bucket.push(doll);
                        }
                        break;
                    }
                }
            }
            return answer;
        }
    }
ArrayList 배열을 선언하여 맨 밑부터 0이 아닌 값만 리스트에 추가하여 moves을 값에 따라 바구니의 제일 위와 같은지 비교하여 넣거나 빼고 같을 때 answer을 2씩 더해주면 해결
다른 사람 풀이를 보니 스택으로 간단히 해결 가능하길래 개선해보았다.
  • 키패드 누르기
    import java.util.*;
    
    class Solution {
        public String solution(int[] numbers, String hand) {
            int[] xy1 = {1, 4}, xy2 = {3, 4};
            Map<Integer, int[]> m = new HashMap<>();
            int num = 1;
            for(int i = 1; i <= 3; i++){
                for(int j = 1; j <= 3; j++){
                    m.put(num++, new int[]{j, i});
                }
            }
            m.put(0, new int[]{2, 4});
            StringBuilder sb = new StringBuilder();
            for(int n : numbers){
                int[] p = m.get(n);
                if(n == 1 || n == 4 || n == 7){
                    sb.append("L");
                    xy1 = p;
                }
                else if(n == 3 || n == 6 || n == 9){
                    sb.append("R");
                    xy2 = p;
                }
                else{
                    int d1 = Math.abs(p[0] - xy1[0]) + Math.abs(p[1] - xy1[1]);
                    int d2 = Math.abs(p[0] - xy2[0]) + Math.abs(p[1] - xy2[1]);
                        if(d1 == d2){
                            if(hand.equals("left")){
                                sb.append("L");
                                xy1 = p;
                            }
                            else{
                                sb.append("R");
                                xy2 = p;
                            }
                        }
                        else if(d1 < d2){
                            sb.append("L");
                            xy1 = p;
                        }
                        else{
                            sb.append("R");
                            xy2 = p;
                        }
                }
            }
            return sb.toString();
        }
    }
키패드의 위치를 x, y 좌표로 생각하여 맵에 해당 숫자 키의 위치를 저장해두고 numbers의 숫자에 따라 누르는 손을 붙이고 왼손, 오른손의 좌표를 갱신하면 해결
  • 신규 아이디 추천 🤔
    class Solution {
        public String solution(String new_id) {
            String answer = new_id.toLowerCase();
            answer = answer.replaceAll("[^a-z0-9-_.]", "");
            answer = answer.replaceAll("\\.{2,}", ".");
            answer = answer.replaceAll("^\\.|\\.$", "");
            if(answer.length() == 0) answer = "a";
            if(answer.length() >= 16) {
                answer = answer.substring(0, 15);
                answer = answer.replaceAll("\\.$", "");
            }
            if(answer.length() <= 2){
                while(answer.length() < 3){
                    answer += answer.charAt(answer.length() - 1);
                }
            }
            return answer;
        }
    }
정규식으로 대체하는 것을 몰라서 찾아보면서 해결하였다. 다음에 이런 정규식에 대해 정리해보아야겠다.
  • 바탕화면 정리
    class Solution {
        public int[] solution(String[] wallpaper) {
            int lux = 51, luy = 51, rdx = -1, rdy = -1;
            for(int i = 0; i < wallpaper.length; i++){
                char[] ch = wallpaper[i].toCharArray();
                for(int j = 0; j < ch.length; j++){
                    if(ch[j] == '#'){
                        lux = Math.min(i, lux);
                        luy = Math.min(j, luy);
                        rdx = Math.max(i + 1, rdx);
                        rdy = Math.max(j + 1, rdy);
                    }
                }
            }
            int[] answer = {lux, luy, rdx, rdy};
            return answer;
        }
    }
wallpaper를 돌면서 최솟값과 최댓값으로 갱신하면 되나 최댓값은 포함하려면 +1을 해야 한다!
  • 개인정보 수집 유효기간 🤔
    import java.util.*;
    
    class Solution {
        public int[] solution(String today, String[] terms, String[] privacies) {
            Map<String, Integer> map = new HashMap<>();
            for(String t : terms){
                String[] split = t.split(" ");
                map.put(split[0], Integer.parseInt(split[1]));
            }
            int todayDays = toDays(today);
            List<Integer> result = new ArrayList<>();
            for(int i = 0; i < privacies.length; i++){
                String[] split = privacies[i].split(" ");
                int start = toDays(split[0]);
                int expire = start + map.get(split[1]) * 28;
                if(expire <= todayDays){
                    result.add(i + 1);
                }
            }
            return result.stream().mapToInt(i -> i).toArray();
        }
        
        private int toDays(String date){
            int y = Integer.parseInt(date.substring(0, 4));
            int m = Integer.parseInt(date.substring(5, 7));
            int d = Integer.parseInt(date.substring(8, 10));
            return y * 12 * 28 + m * 28 + d;
        }
    }
타입별 유효기간을 맵에 저장하여 해당 유효기간을 시작 날짜에 더하여 현재 날짜보다 작거나 같으면 추가하는 방식을 해결
날짜는 모두 일수로 계산하여 비교하면 년도, 달, 일을 비교 할 필요 없이 간단함
  • 유연근무제
    class Solution {
        public int solution(int[] schedules, int[][] timelogs, int startday) {
            int answer = 0;
            for(int i = 0; i < timelogs.length; i++){
                int start = startday;
                int h = schedules[i] / 100;
                int m = schedules[i] % 100;
                m += 10;
                if(m >= 60){
                    h++;
                    m -= 60;
                }
                int time = h * 100 + m;
                boolean get = true;
                for(int j = 0; j < 7; j++){
                    if(start != 6 && start != 0){
                        if(timelogs[i][j] > time){
                            get = false;
                            break;
                        }
                    }
                    start = (start + 1) % 7;
                }
                if(get) answer++;
            }
            return answer;
        }
    }
    
    // 개선
    class Solution {
        public int solution(int[] schedules, int[][] timelogs, int startday) {
            int answer = 0;
            for(int i = 0; i < timelogs.length; i++){
                int start = startday;
                int h = schedules[i] / 100;
                int m = schedules[i] % 100;
                m += 10;
                if(m >= 60){
                    h++;
                    m -= 60;
                }
                int time = h * 100 + m;
                boolean get = true;
                for(int j = 0; j < 7; j++){
                    if(start != 6 && start != 7){
                        if(timelogs[i][j] > time){
                            get = false;
                            break;
                        }
                    }
                    start = (start % 7) + 1;
                }
                if(get) answer++;
            }
            return answer;
        }
    }
문제 요구 사항대로 본인이 정한 출근 시간에서 +10을 하여 시와 분을 따져서 갱신하여 time을 구하고 평일인 시간을 비교하였는데 실패하였음
요일을 비교하는 로직은 잘못됐었다. 토요일과 일요일은 6과 7인데 6과 0으로 비교하였다. 이것만 개선하니 해결되었다
  • 달리기 경주
    import java.util.*;
    
    class Solution {
        public String[] solution(String[] players, String[] callings) {
            String[] answer = players;
            Map<String, Integer> m = new HashMap<>();
            for(int i = 0; i < players.length; i++){
                m.put(players[i], i);
            }
            for(String c : callings){
                int idx = m.get(c);
                answer[idx] = answer[idx - 1];
                answer[idx - 1] = c;
                m.put(answer[idx], idx);
                m.put(answer[idx - 1], idx - 1);
            }
            return answer;
        }
    }
맵으로 해당 플레이어의 인덱스를 넣어두고 불린 사람 배열을 돌면서 앞사람과의 위치를 바꾸고 맵도 갱신하면 해결
  • 공원 산책
    class Solution {
        public int[] solution(String[] park, String[] routes) {
            int x= -1, y = -1;
            int[][] grid = new int[park.length][park[0].length()];
            for(int i = 0; i < park.length; i++){
                for(int j = 0; j < park[i].length(); j++){
                    if(park[i].charAt(j) == 'S'){
                        grid[i][j] = 0;
                        x = i;
                        y = j;
                    }
                    else if(park[i].charAt(j) == 'O')
                        grid[i][j] = 0;
                    else grid[i][j] = 1;
                }
            }
            for(String r : routes){
                String[] s = r.split(" ");
                int cnt = Integer.parseInt(s[1]);
                if(check(s[0], grid, x, y, cnt)){
                    switch(s[0]){
                        case "S":
                            x += cnt;
                            break;
                        case "N":
                            x -= cnt;
                            break;
                        case "E":
                            y += cnt;
                            break;
                        case "W":
                            y -= cnt;
                            break;
                    }
                }
            }
            return new int[]{x, y};
        }
        
        private boolean check(String s, int[][] grid, int x, int y, int cnt){
            if(s.equals("S")){
                if(x + cnt >= grid.length){
                    return false;
                }
                for(int i = 1; i <= cnt; i++){
                    if(grid[x + i][y] == 1) return false;
                }
            }
            else if(s.equals("N")){
                if(x - cnt < 0){
                    return false;
                }
                for(int i = 1; i <= cnt; i++){
                    if(grid[x - i][y] == 1) return false;
                }
            }
            else if(s.equals("E")){
                if(y + cnt >= grid[x].length){
                    return false;
                }
                for(int i = 1; i <= cnt; i++){
                    if(grid[x][y + i] == 1) return false;
                }
            }
            else if(s.equals("W")){
                if(y - cnt < 0){
                    return false;
                }
                for(int i = 1; i <= cnt; i++){
                    if(grid[x][y - i] == 1) return false;
                }
            }
            return true;
        }
    }
    
    // 개선
    import java.util.*;
    
    class Solution {
        public int[] solution(String[] park, String[] routes) {
            int x = -1, y = -1;
            for (int i = 0; i < park.length; i++) {
                if (park[i].contains("S")) {
                    x = i;
                    y = park[i].indexOf("S");
                    break;
                }
            }
            Map<String, int[]> dir = new HashMap<>();
            dir.put("N", new int[]{-1, 0});
            dir.put("S", new int[]{1, 0});
            dir.put("W", new int[]{0, -1});
            dir.put("E", new int[]{0, 1});
            for (String r : routes) {
                String[] s = r.split(" ");
                String op = s[0];
                int cnt = Integer.parseInt(s[1]);
                int nx = x;
                int ny = y;
                boolean isOk = true;
                for (int i = 0; i < cnt; i++) {
                    nx += dir.get(op)[0];
                    ny += dir.get(op)[1];
                    if (nx < 0 || nx >= park.length || ny < 0 || ny >= park[0].length() || park[nx].charAt(ny) == 'X') {
                        isOk = false;
                        break;
                    }
                }
                if (isOk) {
                    x = nx;
                    y = ny;
                }
            }
            return new int[]{x, y};
        }
    }
처음에 방향을 보고 if문과 switch문을 활용하여 풀었는데 비슷한 로직 반복이 많아 개선하였다.
맵으로 해당 방향으로 가는 것을 넣어두고 방향에 따라 좌표 값을 이동시켜 해결하는 것으로 개선하였다.
  • 공원 🤔
    import java.util.*;
    
    class Solution {
        public int solution(int[] mats, String[][] park) {
            int answer = 0;
            Arrays.sort(mats);
            for(int idx = mats.length - 1; idx >= 0; idx--){
                int m = mats[idx];
                for(int i = 0; i <= park.length - m; i++){
                    for(int j = 0; j <= park[i].length - m; j++){
                        if(!park[i][j].equals("-1")) continue;
                        boolean check = true;
                        for(int k = i; k < i + m; k++){
                            for(int l = j; l < j + m; l++){
                                if(!park[k][l].equals("-1")){
                                    check = false;
                                    break;
                                }
                            }
                            if(!check) break;
                        }
                        if(check) return m;
                    }
                }
            }
            return -1;
        }
    }
    
    // 개선
    import java.util.*;
    
    class Solution {
        public int solution(int[] mats, String[][] park) {
            int answer = 0;
            Arrays.sort(mats);
            int n = park.length, m = park[0].length;
            int[][] dp = new int[n][m];
            int max = 0;
            for(int i = 0; i < n; i++){
                if(park[i][0].equals("-1")){
                    dp[i][0] = 1;
                    max = 1;
                }
            }
            for(int i = 0; i < m; i++){
                if(park[0][i].equals("-1")){
                    dp[0][i] = 1;
                    max = 1;
                }
            }
            for(int i = 1; i < n; i++){
                for(int j = 1; j < m; j++){
                    if(!park[i][j].equals("-1")) continue;
                    int now = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
                    max = Math.max(max, now);
                    dp[i][j] = now;
                }
            }
            for(int i = mats.length - 1; i >= 0; i--){
                if(max >= mats[i]) return mats[i];
            }
            return -1;
        }
    }
처음에 -1인 곳에서 1씩 커지면서 체크하려고 했는데 잘 안되서 다른 사람 풀이를 참고해서 공원의 크기에서 돗자리의 크기를 뺀 곳까지 반복문을 돌면서 돗자리 크기가 모두 -1인지 체크하여 해결했는데 for문이 4중 중첩이라 풀이가 썩 마음에 들지 않아 다른 사람의 dp 풀이를 찾아서 보고 개선해보았다.
전처리로 행과 열의 첫 번째 줄을 처리하고 1, 1부터 끝까지 돌면서 -1이면 이 전과 비교하여 +1하는 방식으로 하고 max가 돗자리 크기보다 같거나 커지는 처음 값을 반환
profile
개발자가 되기 위해 열심히 춤추는 중이에요 🕺

0개의 댓글