개인 풀이
코드 리뷰 - 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원칙에 공부하고 원칙에 따라 프로그램 개발 연습 - 예시 코드랑 원칙을 매칭해서 보기(검색하면 많이 나옴)
- 개념에 대해 먼저 보고, 해당 개념을 사용하는 코드를 본다(코드랑 개념을 매칭) - 예시 코드를 많이 보는 게 좋다
'항해 99 > Java' 카테고리의 다른 글
페어 프로그래밍 - 코딩 테스트 5 (1) | 2024.02.17 |
---|---|
Java - 오류 및 예외 처리, 제네릭, Collection (1) | 2024.02.17 |
페어 프로그래밍 - 코딩 테스트 3 (0) | 2024.02.15 |
페어 프로그래밍 - 코딩 테스트 2 (0) | 2024.02.14 |
페어 프로그래밍 - 코딩 테스트 (1) | 2024.02.13 |