본문 바로가기

항해 99/Java

페어 프로그래밍 - 코딩 테스트 4

개인 풀이

코드 리뷰 - ChatGPT

 

40. 가장 가까운 같은 글자

package test2;

public class Test40 {
    //문자열 s의 각 위치마다 자신보다 앞에 나오면서
    //자신과 가장 가까운 곳에 있는 같은 글자의 위치
    // "banana"가 주어진다면
    // b = -1, a = -1, n = -1, a = 2, n = 2, a = 2
    // 자신 앞에 없을 때 -1 반환, 자신 앞에 값이 있을 때 얼마나 앞에 있는지 반환
    // count는 자신을 0으로 했을 때 글자 1개 마다 1씩 증가하도록
    // 모든 단어의 결과를 int[] 배열로 반환

    // 문자열을 split으로 모두 "" 단위로 자르고
    // int[] answer의 크기는 s.length
    // StringBuilder로 Reverse하고 검사도 고려, 앞에 자기랑 같은 값이 있는지 확인해야 됨.
    // 아니면 for문에서 거꾸로 가져와서 검사
    // 이중 for문 둘 다 뒤에서 가져오는데 내부 for문은 외부 for에서 -1을 추가한 값부터 확인.
    // 첫 글자를 가져와서 뒤에 자기랑 같은 글자가 있는지 확인해서 없으면 -1을 answer에 저장
    // 글자를 가져왔을 때
    private static int[] solution(String s) {
        // 거리 정보 담을 배열
        int[] answer = new int[s.length()];
        // 문자열 잘라서 배열에 저장
        String[] str = s.split("");
        // 어떤 첫 단어는 앞에 같은 단어가 없으므로 -1 저장
        answer[0] = -1;

        // 나머지 글자검사
        for (int i = str.length - 1; i >= 0; i--) {
            // 가까운 글자와 거리
            int distance = 0;
            for (int j = i - 1; j >= 0; j--) {
                distance++;
                if (str[i].equals(str[j])) {
                    answer[i] = distance;
                    break;
                } else {
                    answer[i] = -1;
                }
            }
        }
        return answer;
    }

    public static void main(String[] args) {
        int[] answer = solution("cocoa");
        for (int i : answer) {
            System.out.println(i);
        }
    }
}

 

코드 리뷰

  • 가독성 개선
    • 변수 이름을 보다 명시적으로 사용하여 코드의 읽기 쉽게 만듭니다. 예를 들어, str 대신 characters 또는 charArray와 같이 사용할 수 있습니다.
    • 중첩 for-loop 대신 HashMap을 사용하여 최근 등장한 문자의 인덱스를 저장하면 코드의 이해가 쉬워집니다.
  • 성능 개선
    • 문자열을 배열로 변환하는 대신, 문자열에 직접 접근하여 성능을 향상시킬 수 있습니다.
    • 중첩된 for-loop 대신 HashMap을 사용하여 각 문자의 마지막 위치를 추적하면, 각 문자를 확인할 때 마다 이전 위치를 즉시 찾을 수 있어 시간 복잡도를 O(n)으로 줄일 수 있습니다.
  • 확장성 및 유지보수
    • 문자열 처리 로직을 별도의 함수로 분리하여 확장성과 유지보수를 용이하게 할 수 있습니다.

개선 코드

package test2;

import java.util.HashMap;

public class Test40 {
    private static int[] solution(String s) {
        int[] answer = new int[s.length()];
        HashMap<Character, Integer> lastPosition = new HashMap<>();

        for (int i = 0; i < s.length(); i++) {
            char currentChar = s.charAt(i);
            if (lastPosition.containsKey(currentChar)) {
                // 현재 문자와 이전에 같은 문자가 나타난 위치의 차이 계산
                answer[i] = i - lastPosition.get(currentChar);
            } else {
                answer[i] = -1;
            }
            // 현재 문자의 위치를 업데이트
            lastPosition.put(currentChar, i);
        }

        return answer;
    }

    public static void main(String[] args) {
        int[] answer = solution("cocoa");
        for (int i : answer) {
            System.out.println(i);
        }
    }
}
  • String.split("") 대신 String.charAt(i)를 사용하여 문자열에 직접 접근합니다.
  • 각 문자의 마지막 등장 위치를 추적하기 위해 HashMap<Character, Integer>를 사용합니다. 이를 통해 성능을 O(n)으로 개선합니다.
  • 초기값 -1 설정이 필요 없게 됩니다. 문자가 이전에 나타나지 않았다면 자동으로 -1을 할당합니다.

indexOf, lastIndexOf 사용 코드

class Solution {
    public int[] solution(String str) {
        int[] result = new int[str.length()];

        for(int i=0;i<str.length();i++){

            String subStr = str.substring(0,i);
            if(subStr.indexOf(str.charAt(i))==-1) {
                result[i] = -1;
            }else {
                result[i] = i-subStr.lastIndexOf(str.charAt(i));
            }
        }
        return result;
    }
}
  • substring과 indexOf, lastIndexOf의 동작 원리를 알아야 코드를 이해할 수 있음
    • str.charAt(i)로 찾는 단어가 subStr에 없을 경우 indexOf()는 -1을 반환
    • lastIndexOf()는 str.charAt(i)로 찾는 단어가 마지막으로 등장하는 위치를 반환(이 메서드는 문자열의 끝에서 시작해서 문자열의 시작 방향으로 검색을 수행)
    • i - subStr.lastIndexOf(str.charAt(i))를 해주는 이유는 단어 i와 같은 단어의 위치를 i부터 시작해서 얼마나 떨어져 있는지 반환 받기 위해
      • 예: aoa의 경우 첫번 째 a는 마지막 a로부터 2개 떨어져 있음, a(2)o(1)a(0)

 

 

 

41. 푸드 파이터 대회

public class Test41 {
    // 0: 물, 칼로리 적은 순으로 1~3
    // 준비한 음식의 순서 배열 food
    // food[0] = 1(물은 무조건 1개)
    // food[i] 는 칼로리가 작은 순서로 음식의 양이 담김
    // food 배열 length 2~9
    // food의 수 1~10000;
    // 정답 answer의 길이가 3 이상인 경우만 입력으로 주어짐
    // food에 물만 있는 배열은 입력으로 안 들어옴
    // 음식 배치는 1: 3, 2: 4, 3:6 0:1 이라하면 1223330333221로 반환되어야 함
    // 음식 배치는 배열의 값을 /2해서 0을 기준으로 양쪽으로 배분.
    // 음식 갯수가 홀수인 경우는 그냥 나머지 버리기 어차피 int로 받으면 나머지 날아감
    // 음식 1개인 경우 pass

    // 단순하게 하면 0을 제외하고 idx를 저장된 값의 1/2만큼 StringBuilder로 붙이고
    // 다 출력되면 출력 결과 복제 1개 만들고 sb.reverse()
    // 원래 출력 + 0 + reverse를 붙여서 반환
    // 출력을 for문을 사용하냐 stream을 사용하냐 인 거 같은데 map 기능으로
    // map(i -> i * arr[i]/2) 되면 이거 써도 될 거 같은데

    private static String solution(int[] food) {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i < food.length; i++) {
            if (food[i] == 1) {
                continue;
            }
            sb.append(String.valueOf(i).repeat(food[i] / 2));
        }
        String answer = sb.toString()+"0"+sb.reverse().toString();
        return answer;
    }

    public static void main(String[] args) {
        int[] food = {1, 3, 4, 6};
        System.out.println(solution(food));
    }
}

 

코드 리뷰

  • 가독성: 코드는 간결하며, 로직의 기본 아이디어를 잘 전달합니다. 그러나, 특정 조건(food[i] == 1)에서 반복문을 계속 실행하는 대신 건너뛰도록 하는 것은 코드의 의도를 명확하게 전달하지 못할 수 있습니다.
  • 성능: 현재 구현 방식은 각 음식 번호를 해당 음식의 양의 절반만큼 반복하여 문자열로 변환하는 과정을 포함합니다. 이 방식은 작업을 수행하는 데 필요한 시간이 음식의 양에 비례하여 증가합니다.
  • 확장성: 주어진 문제의 조건 내에서는 잘 작동하지만, 코드는 음식의 양이 홀수인 경우를 처리하지 않으며, 물(0번 음식)은 항상 1개라고 가정합니다. 이 가정이 변경될 경우 코드를 수정해야 합니다.
  • 유지보수성: 간결한 코드이지만, 특정 로직(예: food[i] == 1인 경우 건너뛰기)이 왜 필요한지에 대한 주석이 없어, 다른 개발자가 코드를 이해하고 유지보수하는 데 어려움이 있을 수 있습니다.

개선 코드

public class FoodFightArrangement {

    private static String solution(int[] food) {
        StringBuilder leftSide = new StringBuilder();
        StringBuilder rightSide = new StringBuilder();
        
        // 음식 배치 시작
        for (int i = 1; i < food.length; i++) { // 물(0번 음식)을 제외하고 시작
            for (int j = 0; j < food[i] / 2; j++) { // 음식을 2명 분으로 나눈 만큼만 반복
                leftSide.append(i);
                rightSide.insert(0, i); // 오른쪽부터 음식 추가
            }
        }
        
        // 중앙에 물 추가
        String center = "0";
        // 왼쪽과 오른쪽 부분을 합쳐서 최종 문자열 생성
        String answer = leftSide.toString() + center + rightSide.toString();
        
        return answer;
    }

    public static void main(String[] args) {
        int[] food = {1, 3, 4, 6}; // 물, 그리고 칼로리가 적은 순서대로 음식의 양
        System.out.println(solution(food));
    }
}
  • 가독성: 루프 내에서 각 음식 번호를 반복하는 로직을 명확하게 구현하여, 코드의 의도를 더 잘 이해할 수 있습니다.
  • 성능: StringBuilder의 insert(0, i)를 사용하여 오른쪽부터 음식을 추가하는 방식은 좋은 접근이지만, 큰 배열에서는 성능 저하를 일으킬 수 있으므로, 성능을 더 최적화할 수 있는 방법을 고려할 필요가 있습니다. 예를 들어, 두 번째 StringBuilder 사용 대신 처음부터 문자열을 올바른 순서로 생성할 수 있습니다.
  • 확장성과 유지보수성: 코드가 더 명확해지고, 음식의 양이 변경되거나 다른 조건이 추가되는 경우에도 쉽게 대응할 수 있습니다.

 

 

 

42. 콜라 문제

package test2;

public class Test42 {
    // 빈병 a개를 가져다주면 콜라 b병을 주는 마트에서 빈 병 n개를 가져다 주면 콜라 몇 개?
    // 빈병 a개 미만이면 추가 콜라 x
    // a를 주면 b를 주는데 내가 가진 병수는 n일 때 받을 수 있는 콜라 수를 return
    // 제한
    // 1 <= b < a <= n <= 1,000,000
    // 정답은 항상 int 범위를 넘지 않게 주어짐
    // 예시 a = 3, b = 1, n = 20, result = 9
    // 변수로 콜라 갯수를 중간에 저장할 필요성도 있음
    // total: 최종 교환받은 병 수 , take : n에서 가져갈 병수(n / a)
    // reward : 교환 받은 병수(take / a) , n = n - take + reward로 회차마다 변경
    // total += reward도 회차마다
    // n < a가 되는 시점에 반복 종료

    private static int solution(int a, int b, int n) {
        int total = 0;

        while (n >= a) {
            // 교환 받은 콜라 수
            int reward = (n / a) * b;
            // 교환 받은 콜라의 총 합
            total += reward;
            // 가진 빈 콜라병 수(교환 후 남은 빈병 + 교환으로 얻은 콜라)
            n = (n % a) + reward;
        }
        return total;
    }

    public static void main(String[] args) {
//        int n = 10;
        System.out.println(solution(2,1,20));
//        for (int i = 0; i < n; i++) {
//            if (n < 3) {
//                break;
//            }
//            n -= i;
//            System.out.println(n);
//        }
//        System.out.println((18/3)*2);
    }
}

 

코드 리뷰

  • 가독성: 코드는 간결하고, 로직을 이해하기 쉽게 구성되어 있습니다. 변수 이름은 그 목적을 충분히 설명하고 있으며, 주석도 적절히 사용되었습니다.
  • 성능: 주어진 제한사항 내에서 코드의 성능은 충분히 효율적입니다. 반복문을 사용하여 문제를 해결하는 과정에서 필요한 연산만 수행하므로, 불필요한 계산을 최소화합니다.
  • 확장성: 코드는 특정 문제 설정에 맞춰져 있으며, 문제의 조건(a, b, n)에 따라 유연하게 동작합니다. 확장성 측면에서는, 현재 문제의 범위와 조건을 넘어서는 추가 요구사항에 대해서는 조정이 필요할 수 있습니다.
  • 유지보수성: 코드의 단순성과 적절한 주석 사용으로 유지보수성이 좋습니다. 향후 문제의 조건이 변경되거나 다른 유사한 문제에 적용하고자 할 때, 소스 코드를 쉽게 수정할 수 있을 것입니다.

개선 제안

  • 로직의 명확성 증대: 현재 로직은 이해하기 쉽지만, 로직을 더 명확히 하기 위한 주석을 추가하거나, 변수명을 더 구체적으로 할 수 있습니다.
  • 에러 처리: 입력 값에 대한 유효성 검사를 추가하여, 함수가 잘못된 입력(예: a <= b의 경우)에 대해 적절히 대응하도록 할 수 있습니다.

 

 

 

43. 명예의 전당

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Solution {
    public int[] solution(int k, int[] score) {
        int[] answer = new int[score.length];
        List<Integer> list = new ArrayList<>();
        int min = score[0];
        answer[0] = score[0];
        list.add(score[0]);

        if (k > score.length) {
            for (int i=1; i<score.length; i++) {
                list.add(score[i]);
                min = Collections.min(list);
                answer[i] = min;
            }

            return answer;
        }

        for (int i=1; i<k; i++) {
            list.add(score[i]);
            min = Collections.min(list);
            answer[i] = min;
        }

        for (int i=k; i<score.length; i++) {
            if (score[i] >= min) {
                list.add(score[i]);
                list.remove(Integer.valueOf(min));
                min = Collections.min(list);
                answer[i] = min;
            } else {
                answer[i] = min;
            }
        }
        return answer;
    }
}

 

코드 리뷰

  • 가독성: 코드는 상대적으로 이해하기 쉽게 작성되어 있으나, 변수명 min이 실제로는 list에서의 최소값을 의미하는 것이 아니라, 명예의 전당의 최하위 점수를 나타내는 경우가 있어 약간의 혼동을 줄 수 있습니다.
  • 성능: Collections.min(list) 호출은 매번 리스트를 처음부터 끝까지 순회하므로, 이 연산이 반복될 때마다 성능 저하를 일으킬 수 있습니다. 특히, list의 크기가 커질수록 이 문제는 더욱 심각해집니다.
  • 확장성: 코드는 현재 요구사항을 충족하지만, 만약 명예의 전당의 순위를 더 다양하게 관리해야 한다면 현재 구조로는 확장하기 어렵습니다.
  • 유지보수성: if-else와 반복문이 명확하게 구성되어 있어 유지보수는 상대적으로 용이하지만, 성능 개선을 위해 로직을 변경하려면 구조를 상당 부분 수정해야 할 수 있습니다.

개선 코드 - PriorityQueue 사용

import java.util.PriorityQueue;

class Solution {
    public int[] solution(int k, int[] score) {
        int[] answer = new int[score.length];
        PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder()); // 최대 힙 구성

        for (int i = 0; i < score.length; i++) {
            pq.offer(score[i]);
            if (pq.size() > k) {
                pq.poll(); // k+1번째로 낮은 점수 제거
            }
            answer[i] = pq.peek(); // k번째 점수 (최하위 점수) 조회
        }
        return answer;
    }
}
  • 성능: 우선순위 큐를 사용함으로써, 매번 최소값을 찾기 위해 전체 리스트를 순회하는 것보다 더 효율적으로 최하위 점수를 관리할 수 있습니다.
  • 가독성: 우선순위 큐의 사용은 로직의 의도를 명확히 전달하며, 코드의 가독성을 향상시킵니다.
  • 확장성 및 유지보수성: 우선순위 큐를 사용하는 구조는 명예의 전당의 순위 변경이나 다양한 순위 관리 요구에 더 유연하게 대응할 수 있습니다.

 

 

 

페어프로그래밍 코드

36.

package pair4;

/* 숫자 문자열과 영단어 */
public class NumStrEngWords {
    private static int solution(String s) {
        String[] numStr = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

        for (int i=0; i<10; i++) {
            String iStr = String.valueOf(i);
            s = s.replaceAll(numStr[i], iStr);
        }

        return Integer.parseInt(s);
    }

    public static void main(String[] args) {
        int answer = NumStrEngWords.solution("one4seveneight");
        System.out.println("one4seveneight => " + answer);
        answer = NumStrEngWords.solution("1zerotwozero3");
        System.out.println("1zerotowzero3 => " + answer);
    }
}

 

 

 

37.

package pair4;

import java.util.Arrays;

/* 문자열 내 마음대로 정렬하기 */
public class SortStrYouWant {
    private static String[] solution(String[] strings, int n) {

        // n번째 문자를 각 요소 문자열 앞에 붙이기
        // 오름차순 정렬
        for (int i=0; i<strings.length; i++) {
            strings[i] = strings[i].charAt(n) + strings[i];
        }
        Arrays.sort(strings);

        // 붙은 문자 다시 substring 이용해서 잘라내기
        for (int i=0; i<strings.length; i++) {
            int len = strings[i].length();
            strings[i] = strings[i].substring(1, len);
        }

        return strings;

//        Arrays.sort(strings, new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                // 먼저 n번째 문자를 기준으로 비교
//                if (s1.charAt(n) != s2.charAt(n)) {
//                    return s1.charAt(n) - s2.charAt(n);
//                } else {
//                    // n번째 문자가 같다면 전체 문자열 사전순으로 비교
//                    return s1.compareTo(s2);
//                }
//            }
//        });
//        return strings;

    }

    public static void main(String[] args) {
        String[] input1 = {"sun", "bed", "car"};
        int n = 1;
        String[] answer1 = SortStrYouWant.solution(input1, n);
        System.out.println(Arrays.toString(answer1));

        String[] input2 = {"abce", "abcd", "cdx"};
        n = 2;
        String[] answer2 = SortStrYouWant.solution(input2, n);
        System.out.println(Arrays.toString(answer2));

    }
}
//전체 코드 구조
//Arrays.sort 메서드를 사용하여 문자열 배열 strings를 정렬합니다.
//정렬 기준은 Comparator 인터페이스의 compare 메서드를 오버라이드하여 구현합니다.

//Arrays.sort 메서드
//Arrays.sort(Object[] a, Comparator<? super T> c)는 주어진 배열 a를
//주어진 Comparator가 제공하는 순서에 따라 정렬합니다.
//이 경우 배열 a는 문자열 배열 strings이고, Comparator는 익명 클래스로 제공됩니다.

//Comparator<String> 익명 클래스
//new Comparator<String>() { ... }는 Comparator 인터페이스의 익명 구현체를 생성합니다.
//이 구현체는 문자열 두 개를 비교하는 로직을 제공합니다.

//compare 메서드 오버라이드
//public int compare(String s1, String s2) 메서드는 두 문자열 s1과 s2를 비교하여
//정렬 순서를 결정합니다.
//이 메서드는 정수를 반환하며, 반환 값은 다음과 같은 의미를 가집니다:
//음수: s1이 s2보다 앞에 오도록 정렬합니다.
//0: s1과 s2의 순서를 변경하지 않습니다.
//양수: s1이 s2보다 뒤에 오도록 정렬합니다.

//비교 로직
//n번째 문자 비교: s1.charAt(n) != s2.charAt(n)을 사용하여 두 문자열의 n번째 문자를 비교합니다.
//문자가 서로 다른 경우,
//이 두 문자의 ASCII 값 차이(s1.charAt(n) - s2.charAt(n))를 반환하여 정렬 순서를 결정합니다.
//전체 문자열 사전순 비교: n번째 문자가 동일한 경우, s1.compareTo(s2)를 사용하여
//두 문자열 전체를 사전순으로 비교합니다.
//이는 두 문자열이 사전순으로 어떤 순서로 정렬될지 결정합니다.
//반환 값
//정렬된 문자열 배열 strings를 반환합니다. 이 배열은 n번째 문자를 기준으로
//오름차순으로 정렬되었으며, n번째 문자가 같은 경우 전체 문자열의 사전순으로 정렬되었습니다.

 

 

 

38.

package pair4;

import java.util.Arrays;

/* K번째 수 */
public class KthNum {
    private static int[] solution(int[] array, int[][] commands) {
        int[] answer = new int[commands.length];
        for (int i=0; i<commands.length; i++) {
            int[] arr = new int[commands[i][1] - commands[i][0] + 1];
            for (int j = 0; j<arr.length; j++) {
                arr[j] = array[commands[i][0] - 1 + j];
            }
            Arrays.sort(arr);
            answer[i] = arr[commands[i][2] - 1];
        }

//        answer = new int[commands.length];
//        for (int i = 0; i < commands.length; i++) {
//            int idx1 = commands[i][0]-1;
//            int idx2 = commands[i][1]-1;
//            int idx3 = commands[i][2]-1;
//            int[] cutArray = IntStream.rangeClosed(idx1, idx2)
//                    .map(n -> array[n]).sorted().toArray();
//            answer[i] = cutArray[idx3];
//        }
//
        return answer;
    }

    public static void main(String[] args) {
        int[] array = {1,5,2,6,3,7,4};
        int[][] commands = {{2,5,3}, {4,4,1}, {1,7,3}};
        int[] answer = KthNum.solution(array, commands);
        System.out.println(Arrays.toString(answer));
    }
}

 

 

 

39.

package pair4;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/* 두 개 뽑아서 더하기
 * 정수 배열 `numbers`가 주어집니다.
 * `numbers`에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.
 * */
public class TakeTwoAdd {
    private static int[] solution(int[] numbers) {
        Set<Integer> sumSet = new HashSet<>();
        for (int i=0; i<numbers.length - 1; i++) {
            for (int j=i+1; j<numbers.length; j++) {
                sumSet.add(numbers[i] + numbers[j]);
            }
        }

        return sumSet.stream().mapToInt(i -> i).sorted().toArray();
    }

    public static void main(String[] args) {
        int[] numbers1 = {2,1,3,4,1};
        int[] answer1 = TakeTwoAdd.solution(numbers1);
        System.out.println(Arrays.toString(answer1));

        int[] numbers2 = {5,0,2,7};
        int[] answer2 = TakeTwoAdd.solution(numbers2);
        System.out.println(Arrays.toString(answer2));
    }
}

 

 

 

40.

package pair4;

import java.util.Arrays;

/* 가장 가까운 글자 */
public class NearestLetter {
    private static int[] solution(String s){
        // substring 사용
        int[] answer = new int[s.length()];

        for (int i = 0; i < s.length(); i++) {
            int index = s.indexOf(s.charAt(i));
            if (index == i) {
                answer[i] = -1;
            } else {
                answer[i] = i - index;
                s = s.substring(0, index) + ' ' + s.substring(index + 1);
            }
        }
        return answer;

        // lastIndexOf 사용
/*        int[] result = new int[str.length()];

        for(int i=0;i<str.length();i++){

            String subStr = str.substring(0,i);
            if(subStr.indexOf(str.charAt(i))==-1) {
                result[i] = -1;
            }else {
                result[i] = i-subStr.lastIndexOf(str.charAt(i));
            }
        }
        return result;*/

//        str.charAt(i)로 찾는 단어가 subStr에 없을 경우 indexOf()는 -1을 반환
//        lastIndexOf()는 str.charAt(i)로 찾는 단어가 마지막으로 등장하는 위치를 반환
//        (이 메서드는 문자열의 끝에서 시작해서 문자열의 시작 방향으로 검색을 수행)
//        i - subStr.lastIndexOf(str.charAt(i))를 해주는 이유는 단어 i와
//        같은 단어의 위치를 i부터 시작해서 얼마나 떨어져 있는지 반환 받기 위해
//        (예: aoa의 경우 첫번 째 a는 마지막 a로부터 2개 떨어져 (a2o1a0) 있음)
    }

    public static void main(String[] args) {
        String s = "banana";
        int[] answer = NearestLetter.solution(s);
        System.out.println(Arrays.toString(answer));
    }
}

 

 

 

41.

package pair4;

/* 푸드 파이트 대회 */
public class FoodFight {
    private static String solution(int[] food) {
        // food 배열의 각 요소를 2로 나눈 몫 개수 만큼 숫자를 Stringbuilder.append
        // 3 / 2 = 1 => 1
        // 4 / 2 = 2 => 1 + 22
        // ...
        // 122333 + 0
        // 122333을 저장한 String을 뒤집은 후
        // 1223330에 더해주기

        StringBuilder sb = new StringBuilder();
        for (int i=1; i<food.length; i++) {
            int cnt = food[i] / 2; // 2로 나눈 몫
            sb.append(String.valueOf(i).repeat(food[i] / 2));
        }

        String s = sb.toString();
        String reverse = sb.reverse().toString();

        return s + "0" + reverse;
//        return sb.toString()+"0"+sb.reverse().toString();
    }

    public static void main(String[] args) {

    }
}


 

 

 

42.

package pair4;

/* 콜라 문제 */
public class Cola {
    /**
     * a = 마트에 주어야 하는 콜라수
     * b = 마트가 주는 콜라병 수
     * n = 처음 콜라 개수
     */
    // 처음 콜라 개수(n) / 마트에 주어야 하는 콜라수(a) * b => 새로 받은 콜라 수
    // n % a = 주지 못한 콜라수
    // n = 주지 못한 콜라수 + 새로 받은 콜라 수
    //...
    // n < a => 반복 종료
    private static int solution(int a, int b, int n) {
        // 총 새로받은 콜라수
        int answer = 0;

        // 한 번 교환할 때 받은 새로운 콜라 수
        int newCola = 0;
        while (n >= a) {
            newCola = (n / a) * b;
            answer += newCola;
            n = (n % a) + newCola;
        }

        return answer;
    }

    public static void main(String[] args) {

    }
}

 

 

 

43.

package pair4;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/* 명예의 전당 */
public class HallOfFame {
    private static int[] solution(int k, int[] score) {
        // 명예의 전당에는 총 k개의 점수만 들어 갈 수 있다
        // 명예의 전당 배열(길이=k)에서 가장 작은 수 = 발표 점수

        int[] answer = new int[score.length];
        List<Integer> showList = new ArrayList();

        for(int i=0; i < score.length; i++) {
            if(i < k) {
                showList.add(score[i]);
            }
            else {
                // score[i] 와 list 내 값 비교
                if(score[i] >= showList.get(0)){
                    showList.remove(0);
                    showList.add(score[i]);
                }
            }
            Collections.sort(showList);
            answer[i] = showList.get(0);
        }
        return answer;

//        int min = score[0];
//        answer[0] = score[0];
//        list.add(score[0]);
//
//        if (k > score.length) {
//            for (int i=1; i<score.length; i++) {
//                list.add(score[i]);
//                min = Collections.min(list);
//                answer[i] = min;
//            }
//
//            return answer;
//        }
//
//        for (int i=1; i<k; i++) {
//            list.add(score[i]);
//            min = Collections.min(list);
//            answer[i] = min;
//        }
//
//        for (int i=k; i<score.length; i++) {
//            if (score[i] >= min) {
//                list.add(score[i]);
//                list.remove(Integer.valueOf(min));
//                min = Collections.min(list);
//                answer[i] = min;
//            } else {
//                answer[i] = min;
//            }
//        }

//        return answer;

    }

    public static void main(String[] args) {
        HallOfFame.solution(8, new int[]{10,100,20,150,1,100,200});
    }
}

 

 

 

PriorityQueue(우선 순위 큐)

표준 큐 데이터 구조의 한 형태, 각 요소가 우선 순위를 가지며, 우선 순위가 가장 높은 요소가 가장 먼저 제거되는 특징을 가짐.

특징

  • 우선 순위 기반 : 큐에서 요소를 제거할 때, 우선 순위가 가장 높은 요소가 먼저 나옴
    • 요소의 우선 순위는 요소를 추가할 때 지정하거나, 요소의 자연스러운 순서를 따름(숫자의 경우 낮은 숫자가 높은 우선 순위)
  • 이진 힙 구조 사용 : 내부적으로 이진 힙(binary heap) 데이터 구조를 사용하여 구현, 요소의 추가 및 제거 작업이 로그 시간 복잡도를 가짐  (O(log n))
  • 정렬 상태 유지 : 우선 순위 큐는 내부적으로 전체가 정렬된 상태를 유지하지 않지만, 우선 순위가 가장 높은 요소에 쉽게 접근할 수 있음

사용 시 주의 사항

  • PriorityQueue는 스레드 안전(Thread-safe)하지 않음, 멀티 스레드 환경에서는 java.util.concurrent.PriorityBlockingQueue 클래스를 사용해야 함
  • PriorityQueue에 저장되는 객체는 비교 가능해야 함, 객체가 Comparable 인터페이스를 구현하거나, 생성 시 Comparator를 제공해야 함을 의미

 

 

멘토링 내용 정리

  • 나만의 위키 - 아는 정보를 블로그 등에 정리하고 모르는 내용을 공부하는 게 좋다
  • 내가 모르는 함수를 사용한 코드를 내가 작성한 코드와 비교해 보고 어떤 기능을 수행하는 함수인지 알고 넘어가자
  • 정규 표현식은 정규 표현식이 필요할 때 테스트 사이트에서 만들어서 사용
  • 솔리드 5원칙에 공부하고 원칙에 따라 프로그램 개발 연습 - 예시 코드랑 원칙을 매칭해서 보기(검색하면 많이 나옴)
  • 개념에 대해 먼저 보고, 해당 개념을 사용하는 코드를 본다(코드랑 개념을 매칭) - 예시 코드를 많이 보는 게 좋다