프로그래머스 Lv. 1 첫페이지

지니🧸·2024년 4월 3일
0

알고리즘

목록 보기
14/43
post-thumbnail

일주일 안에 다 풀어볼 목표라 코드가 더러운건 ..ㅎㅎ

1. 가장 많이 받은 선물

풀이

다음 달에 A가 선물을 받게 될지의 기준은 딱 두가지다

  1. B가 준 선물보다 B에게 준 선물이 더 많은지 (이 경우 받은 역사는 필요 없음)
  2. (1)에서 동점이라면 (서로 안 준 경우 포함) 선물 지수가 높은지

그래서 2차 배열로 서로 선물을 준 기록을 저장하고, 별도의 배열에 각자 선물 지수를 계산했다.

두가지 자료구조에 기반해 값을 비교하여 답을 구했다.

코드

import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

class Solution {
    public int solution(String[] friends, String[] gifts) {
        int answer = 0;
        
        List<Integer> gifts_count = new ArrayList<>();
        for (int i = 0; i < friends.length; i++) {
            gifts_count.add(0);
        }
        int[][] gifts_graph = new int[friends.length][friends.length];
        
        for (int i = 0; i < gifts.length; i++) {
            String sender = gifts[i].split(" ")[0];
            String receiver = gifts[i].split(" ")[1];
            
            int idx_sender = Arrays.asList(friends).indexOf(sender);
            int idx_receiver = Arrays.asList(friends).indexOf(receiver);
            
            gifts_count.set(idx_sender, gifts_count.get(idx_sender)+1);
            gifts_count.set(idx_receiver, gifts_count.get(idx_receiver)-1);
            
            gifts_graph[idx_sender][idx_receiver] += 1;
            
        }
        
        int[] next = new int[friends.length];
        for (int i = 0;i < friends.length; i++) {
            for (int j = i + 1; j < friends.length; j++) {
                if (gifts_graph[i][j] > gifts_graph[j][i]) {
                    next[i] += 1;
                } 
                else if (gifts_graph[i][j] < gifts_graph[j][i]) {
                    next[j] += 1;
                }
                else {
                    if (gifts_count.get(i) > gifts_count.get(j)) {
                        next[i] += 1;
                    } else if (gifts_count.get(i) < gifts_count.get(j)) {
                        next[j] += 1;
                    }
                }
            }
        }
        
        for (int i = 0; i < friends.length; i ++) {
            if (next[i] > answer) {
                answer = next[i];
            }
        }
        
        return answer;
    }
}

2. [PCCP 기출문제] 1번 / 붕대 감기

풀이

몬스터가 공격을 하는 시각마다 다음을 수행한다

  1. 몇 초 동안 붕대감기 기술 썼는지
  2. 붕대감기 기술 시전시간을 몇번 달성했는지 (연속시간 횟수 기록해서 추가 회복 계산)
  3. 몬스터의 공격을 받고 죽었는지

코드

class Solution {
    public int solution(int[] bandage, int health, int[][] attacks) {
        int answer = 0;
        
        int skillTime = bandage[0];
        int recoverPerSec = bandage[1];
        int addRecover = bandage[2];
        
        int currentHealth = health;
        for (int i = 0; i < attacks.length; i ++) {
            int prev = 0;
            int focusedTime = 0;

            if (i != 0) {
                prev = attacks[i-1][0];
            }
            focusedTime = (attacks[i][0] - prev - 1);
            currentHealth += focusedTime * recoverPerSec;
            
            int focusSuccess = focusedTime / skillTime;
            currentHealth += focusSuccess * addRecover;
            currentHealth = Math.min(health, currentHealth);            
            currentHealth -= attacks[i][1];
            
            if (currentHealth <= 0) {
                return -1;
            }
        }
        
        answer = currentHealth;
        
        return answer;
    }
}

3. [PCCE 기출문제] 9번 / 이웃한 칸

class Solution {
    public int solution(String[][] board, int h, int w) {
        int answer = 0;
        String color = board[h][w];
        
        int[] dx = {0, 0, -1, 1};
        int[] dy = {-1, 1, 0, 0};
        
        for (int i = 0; i < 4; i ++) {
            int nx = dx[i] + w;
            int ny = dy[i] + h;
            
            boolean isValid = nx >= 0 && nx < board.length && ny >= 0 && ny < board.length;
            
            if (isValid && board[ny][nx].equals(color)) {
                answer += 1;
            }
        }
        
        return answer;
    }
}

4. [PCCE 기출문제] 10번 / 데이터 분석

풀이

각 로우마다 다음을 수행한다 (정답배열은 2차 배열로 정의)

  1. 기준 컬럼 값이 제시값보다 작은지
  2. 작으면 정답 배열에 [인덱스, sort_by 컬럼값]를 추가

그 다음, sort_by 컬럼값으로 정답 배열을 정렬하고 리턴한다.

코드

import java.util.*;

class Solution {
    public int[][] solution(int[][] data, String ext, int val_ext, String sort_by) {
        int[][] answer = {};
                
        int column = 0;
        if (ext.equals("date")) {
            column = 1;    
        } else if (ext.equals("maximum")) {
            column = 2;
        } else if (ext.equals("remain")) {
            column = 3;
        }
        
        int sortColumn = 0;
        if (sort_by.equals("date")) {
            sortColumn = 1;    
        } else if (sort_by.equals("maximum")) {
            sortColumn = 2;
        } else if (sort_by.equals("remain")) {
            sortColumn = 3;
        }
        
        int[][] validData = new int[data.length][data[0].length];
        for (int i = 0; i < data.length; i ++) {
            if (data[i][column] < val_ext) {
                validData[i][0] = i;
                validData[i][1] = data[i][sortColumn];
            } 
        }
        
        Arrays.sort(validData, Comparator.comparingInt(pair -> pair[1]));
        
        List<int[]> sortedValidData = new ArrayList<>();
        for (int i = 0; i < validData.length; i ++) {
            System.out.println(i +": " + validData[i][1]);
            if (validData[i][1] != 0) {
                sortedValidData.add(data[validData[i][0]]);
            }
        }
        
        answer = new int[sortedValidData.size()][data[0].length];
        for (int i = 0; i < sortedValidData.size(); i ++) {
            answer[i] = sortedValidData.get(i);
        }
        return answer;
    }
}

5. 달리기 경주

풀이

나는 HashMap을 두개 정의해서 bidirectional map 처럼 사용했다.

callings를 iterate하면서 추월하는 선수의 랭킹을 올려주고, 추월하는 선수의 기존 랭킹보다 한단계 높았던 선수의 랭킹을 내려줬다.

코드

import java.util.*;
class Solution {
    public String[] solution(String[] players, String[] callings) {
        String[] answer = new String[players.length];
        
        Map<String, Integer> playersRanks = new HashMap<>();
        Map<Integer, String> ranksPlayers = new HashMap<>();
        
        for (int i = 0; i < players.length; i ++) {
            playersRanks.put(players[i], i+1);
            ranksPlayers.put(i+1, players[i]);
        }
        
        for (int i = 0; i < callings.length; i++) {
            String passerPlayer = callings[i];
            int calledRank = playersRanks.get(passerPlayer);
            int passedRank = calledRank-1;
            String passedPlayer = ranksPlayers.get(passedRank);
            
            playersRanks.put(passerPlayer, passedRank);
            playersRanks.put(passedPlayer, calledRank);
            
            ranksPlayers.put(passedRank, passerPlayer);
            ranksPlayers.put(calledRank, passedPlayer);
        }
        
        Map<Integer, String> sortedMap = new TreeMap<>(ranksPlayers);
        int idx = 0;
        for (Map.Entry<Integer, String> entry : sortedMap.entrySet()) {
            answer[idx] = entry.getValue();
            idx += 1;
        }
        
        return answer;
    }
}

6. 추억 점수

풀이

그리운 인물과 그리움 점수를 HashMap으로 매핑하고

사진 루프 안에서 각 인물이 HashMap에 키로 존재하는지 확인하고, 존재하는 경우 그리움 점수에 추가한다.

코드

import java.util.*;
class Solution {
    public int[] solution(String[] name, int[] yearning, String[][] photo) {
        int[] answer = new int[photo.length];
        
        Map <String, Integer> nameYearning = new HashMap<>();
        for (int i = 0; i < name.length; i++) {
            nameYearning.put(name[i], yearning[i]);
        }
        
        for (int i = 0; i < photo.length; i ++) {
            int ans = 0;
            for (int j = 0; j < photo[i].length; j ++) {
                String appeared = photo[i][j];
                if (nameYearning.containsKey(appeared)) {
                    ans += nameYearning.get(photo[i][j]);
                }
                
            }
            answer[i] = ans;
        }
        
        
        return answer;
    }
}

7. 대충 만든 자판

풀이

keymap의 모든 알파벳과 그 알파벳에 도달할 수 있는 가장 작은 횟수로 HashMap을 만든다.

코드

import java.util.*;
class Solution {
    public int[] solution(String[] keymap, String[] targets) {
        int[] answer = new int[targets.length];
        
        Map<String, Integer> keyboard = new HashMap<>();
        
        for (int i = 0; i < keymap.length; i ++) {
            for (int j = 0; j < keymap[i].length(); j++) {
                String letter = keymap[i].substring(j, j+1);
                if (keyboard.containsKey(letter)) {
                    if (keyboard.get(letter) > j) {
                        keyboard.put(letter, j+1);
                    }
                } else {
                    keyboard.put(letter, j+1);
                }
            }
        }
        for (int i = 0; i < targets.length; i ++) {
            int cost = 0;
            boolean exists = true;
            for (int j = 0; j < targets[i].length(); j++) {
                String letter = targets[i].substring(j, j+1);
                if (keyboard.containsKey(letter)) {
                    cost += keyboard.get(letter);  
                } else {
                    exists = false;
                    break;
                }
            }
            if (exists) {
                answer[i] = cost;
            } else {
                answer[i] = -1;
            }
        }
        
        return answer;
    }
}

8. 둘만의 암호

풀이

알파벳 26자를 순서대로 나열한 String을 정의하고, skip에 있는 알파벳들은 그 변수에서 제거한다.

코드

import java.util.*;
class Solution {
    public String solution(String s, String skip, int index) {
        String answer = "";
        
        String alphabets = "abcdefghijklmnopqrstuvwxyz";
        for (int i =0; i < skip.length(); i++) {
            int idx = alphabets.indexOf(skip.charAt(i));
            alphabets = alphabets.substring(0, idx) + alphabets.substring(idx+1);
        }
        for (int i =0; i < s.length(); i++) {
            String letter = s.substring(i, i+1);
            int currentIndex = alphabets.indexOf(letter);
            int newIdx = currentIndex;
            if (newIdx + index < alphabets.length()) {
                answer += alphabets.charAt(newIdx + index);
            } else {
                
                newIdx = (index - (alphabets.length()-1-currentIndex)) % alphabets.length() -1;
                
                if (newIdx == -1) {
                    newIdx = alphabets.length()-1;
                }
                
                answer += alphabets.charAt(newIdx);
            }
        }
        
        return answer;
    }
}

9. 개인정보 수집 유효기간

개념

  1. 2022.05.19.-로 대체하면 LocalDate 객체로 파싱할 수 있다
  2. LocalDateplusMonths(int n) 함수가 있다
  3. compareToLocalDate 객체 간 비교가 가능하다

코드

import java.util.*;
import java.time.*;
class Solution {
    public int[] solution(String today, String[] terms, String[] privacies) {

        LocalDate todayDate = LocalDate.parse(today.replace('.', '-'));
        Map<String, Integer> termsMap = new HashMap<>();
        
        for (int i =0; i < terms.length; i++) {
            String type = terms[i].split(" ")[0];
            int period = Integer.parseInt(terms[i].split(" ")[1]);
            termsMap.put(type, period);
        }
        
        List<Integer> destroyList = new ArrayList<>();
        for (int i = 0; i < privacies.length; i++) {
            LocalDate startDate = LocalDate.parse(privacies[i].split(" ")[0].replace('.', '-'));
            String type = privacies[i].split(" ")[1];
            int comparison = startDate.plusMonths(termsMap.get(type)).compareTo(todayDate);
            if (comparison <= 0) {
                destroyList.add(i+1);
            }
        }
        
        
        
        int[] answer = new int[destroyList.size()];
        for (int i = 0; i < destroyList.size(); i++) {
            answer[i] = destroyList.get(i);
        }
        
        return answer;
    }
}

10. 크기가 작은 부분 문자열

class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        int plen = p.length();
        long pLong = Long.parseLong(p);
        
        
        for (int i =0; i < t.length() - plen + 1; i++) {
            String target = t.substring(i, i+plen);
            int idx = 0;
            
            System.out.println(Long.parseLong(target));
            if (Long.parseLong(target) <= pLong) {
                answer ++;
            }
        }
        return answer;
    }
}

제한사항을 잘 확인해서 int가 아닌 long을 사용하는 것이 관건

11. 가장 가까운 같은 글자

풀이

지금 인덱스 전까지의 s를 문자열에 저장해 현재 인덱스의 알파벳이 어디서 마지막으로 발생했는지 확인한다

코드

class Solution {
    public int[] solution(String s) {
        int[] answer = new int[s.length()];
        for (int i =0; i < s.length(); i++) {
            String letter = s.substring(i, i+1);
            String beforeLetter = s.substring(0,i);
            int find = beforeLetter.lastIndexOf(letter);
            if (find == -1) {
                answer[i] = find;
            } else {
                answer[i] = i - find;
            }
        }
        return answer;
    }
}

12. 문자열 나누기

코드

class Solution {
    public int solution(String s) {
        int answer = 0;
        char x = s.charAt(0);
        s = s.substring(1);
        int same = 1;
        int diff = 0;
        
        if (s.length() == 0) {
            return 1;
        }
        
        while (s.length()> 0) {
            char c = s.charAt(0);
            s = s.substring(1);
            if (c == x) {
                same ++;
            } else {
                diff ++;
            }
            if (same == diff) {
                if (s.length() > 0) {
                    x = s.charAt(0);
                }
                answer ++;
            }
            if (s.length() == 0 && same != diff) {
                answer ++;
            }
        }
        
        return answer;
    }
}

13. 명예의 전당 (1)

import java.util.*;
class Solution {
    public int[] solution(int k, int[] score) {
        int[] answer = new int[score.length];
        List<Integer> legends = new ArrayList<>();
        for (int i = 0; i < score.length; i++) {
            if (legends.size() < k) {
                legends.add(score[i]);
            } 
            
            else {
                int min = solveMin(legends);
                if (score[i] >= min) {
                    int idx = legends.indexOf(min);
                    legends.remove(idx);
                    legends.add(score[i]);
                }
            }
            
            
            
            answer[i] = solveMin(legends);
        }
        
        
        return answer;
    }
    
    private int solveMin(List<Integer> l) {
        int min = l.get(0);
        for (Integer element : l) {
            if (element < min) {
                min = element;
            }
        }
        return min;
    }
}

14. 기사단원의 무기

class Solution {
    public int solution(int number, int limit, int power) {
        int answer = 0;
        
        for (int i = 1; i <= number; i ++) {
            int attack = getNumDivisors(i);
            if (attack > limit) {
                attack = power;
            }
            answer += attack;
        }
        
        return answer;
    }
    
    private int getNumDivisors(int num) {
        int count = 0;
        for (int i = 1; i * i <= num; i++) {
            if (num % i == 0) {
                if (num == i * i) {
                    count += 1;
                } else {
                    count += 2;
                }
            }
        }
        return count;
    }
}

15. 과일 장수

풀이

score 배열을 iterate해서 각 인덱스의 값이 (인덱스+1)점의 사과 개수를 표현하는 배열을 만든다

  • arr[0] = 2면 1점인 사과가 2개라는 뜻.

그 다음 모든 사과를 셀 때까지 loop을 돌면서 이익을 계산한다.

코드

import java.util.*;
class Solution {
    public int solution(int k, int m, int[] score) {
        int answer = 0;

        
        int[] tap = new int[k];
        
        for (int j = 0; j < score.length; j++) {
            tap[score[j]-1] += 1;
        }
        
        
        int totalAmount = score.length;
        
        int countingAmount = 0;
        int idx = tap.length-1;
        int inBox = 0;
        while (countingAmount < totalAmount) {
            if (tap[idx] <= 0) {
                idx -=1;
                if (idx == -1) {
                    break;
                }
                continue;
            }
            
            int remove = Math.min(tap[idx], m-inBox);
            inBox += remove;
            tap[idx] -= remove;
            countingAmount += remove;
            if (inBox == m) {
                answer += (idx+1) * m;
                inBox = 0;
            }
        }
        
        
        return answer;
    }
}

16. 푸드 파이트 대회

class Solution {
    public String solution(int[] food) {
        String answer = "0";
        
        for (int i = food.length-1; i >=1; i--) {
            int count = food[i];
            if (count % 2 == 1) {
                count -=1;
            }
            String addition = Integer.toString(i).repeat(count/2);
            answer = addition + answer + addition;
        }
        
        return answer;
    }
}

출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges

profile
우당탕탕

0개의 댓글