diff --git a/seojimin/week9/1202/Main.java b/seojimin/week9/1202/Main.java new file mode 100644 index 0000000..a32eb13 --- /dev/null +++ b/seojimin/week9/1202/Main.java @@ -0,0 +1,79 @@ +/** + * 백준 1202번 - 보석 도둑 [정렬 알고리즘] + * + * [문제 요약] + * - 보석 N개와 가방 K개가 주어짐 + * - 보석은 각각의 무게(W)와 가치(V)를 지니고 있다 + * - 가방은 담을 수 있는 최대 용량(C)이 정해져있다 + * - 각 가방에 단 하나에 보석만을 담을 수 있을 때, 최댓값을 구하자 + * + * [해결 방법] + * - 보석과 가방을 모두 하나의 리스트에 담는다 + * - 단 가방의 경우 V가 들어갈 자리에 -1을 넣어 가방임을 표시 + * - 정렬을 진행하며, 기본적으로 무게(용량)을 기준으로 오름차순 정렬을 진행 + * - 무게가 동일한 경우 가치가 높은 순으로 내림차순 정렬 + * - 리스트를 순회하며, 우선순위 큐에 가치를 넣어주고 + * - 가방의 차례가 되면 지금까지의 우선순위 큐중 가장 큰 값을 가져와 결과에 더한다 + * - 해당 방식을 반복한다 + * + * [시간 복잡도] + * 정렬: O((N + K) log (N + K)) + * 우선순위 큐 삽입/삭제: O((N + K) log N) + * 전체: O((N + K) log N) + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.PriorityQueue; + +public class Main { + + static long solve(int n, int k, int[][] jewels, int[] bags){ + + List inputs = new ArrayList<>(); + for (int i = 0; i < n; i++) { + inputs.add(new int[]{jewels[i][0], jewels[i][1]}); + } + + for (int i = 0; i < k; i++) { + int temp = bags[i]; + inputs.add(new int[]{temp, -1}); + } + + // 무게 기준 오름차순 정렬, 무게 같으면 가치 내림차순 + inputs.sort((o1, o2) -> { + if (o1[0] == o2[0]) return o2[1] - o1[1]; + return o1[0] - o2[0]; + }); + + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + long result = 0; + + for (int[] input : inputs) { + int value = input[1]; + + if (value == -1) { + // 가방인 경우 → 지금까지 PQ에 들어온(즉, 이 가방 무게 이하인) 보석 중 제일 비싼 거 선택 + if (!pq.isEmpty()) { + result += pq.poll(); + } + } else { + // 보석인 경우 → PQ에 가치 추가 + pq.offer(value); + } + } + + return result; + } + + public static void main(String[] args) { + int[][] jewels = new int[][]{ + {1,65}, + {5,23}, + {2,99} + }; + + System.out.println(solve(3, 2, jewels, new int[]{10, 2})); + } +} \ No newline at end of file diff --git a/seojimin/week9/1744/Main.java b/seojimin/week9/1744/Main.java new file mode 100644 index 0000000..a9c5823 --- /dev/null +++ b/seojimin/week9/1744/Main.java @@ -0,0 +1,75 @@ +/** + * 백준 1744번 - 수 묶기 [정렬 알고리즘] + * + * [문제 요약] + * - 길이가 N인 수열이 주어짐 + * - 위치 상관없이 두 개씩 묶어 곱하거나, 각각을 더하도록 해서 수열의 모든 요소의 합의 최댓값 구하기 + * + * [해결 방법] + * - 양수인 케이스와 음수인 케이스로 분리 + * - 양수의 경우 내림차순 정렬 후 순회하며 2개씩 묶어 곱한 뒤 더하고 1개 남은 경우 그냥 더하기 + * - 단, 묶어질 숫자에 1이 포함된 경우 묶지 않고 따로 더하기(1을 곱하면 그대로이기에 오히려 각각을 더하는게 더 크다) + * - 음수의 경우 절대값이 큰 요소끼리 묶어야 커지므로, 오름차순 정렬 + * - 1개의 값이 남았을 경우, 0이 수열에 포함되는지 확인 + * - 0이 있으면 해당 음수와 0을 곱하는게 이득이기에 곱했다는 가정하에 더하지 않음 + * - 0이 없으면 해당 음수를 총합에 더함 + * + * [시간 복잡도] + * - O(N log N) + */ + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +public class Main { + + static int solve(int n, int[] input){ + + List plusList = new ArrayList<>(); + List minusList = new ArrayList<>(); + boolean zero = false; + + for (int i = 0; i < n; i++) { + int temp = input[i]; + if (temp < 0) minusList.add(temp); + else if (temp == 0) zero = true; + else plusList.add(temp); + } + + plusList.sort(Collections.reverseOrder()); + Collections.sort(minusList); + + int sum = 0; + + // plusList부터 시작 + for (int i = 0; i < plusList.size(); i++) { + int now = plusList.get(i); + + if (i + 1 < plusList.size() && now > 1 && plusList.get(i + 1) > 1) { + sum += now * plusList.get(i + 1); + i++; + } else { + sum += now; + } + } + + // minus 케이스 + for (int i = 0; i < minusList.size(); i++) { + if (i + 1 < minusList.size()) { + sum += minusList.get(i) * minusList.get(i + 1); + i++; + } else { + // 남는 음수 하나가 있을 때 + if (!zero) sum += minusList.get(i); // 0이 없으면 더함 + // 0이 있으면 곱해서 0이 되므로 아무것도 안 더함 + } + } + + return sum; + } + + public static void main(String[] args) { + System.out.println(solve(6, new int[]{0,1,2,4,3,5})); + } +} \ No newline at end of file diff --git a/seojimin/week9/1946/Main.java b/seojimin/week9/1946/Main.java new file mode 100644 index 0000000..e2bc7e2 --- /dev/null +++ b/seojimin/week9/1946/Main.java @@ -0,0 +1,89 @@ +/** + * 백준 1946번 - 신입사원 [정렬 알고리즘] + * + * [문제 요약] + * - 두가지 유형의 순위가 주어진다 + * - 특정 후보보다 두 가지 유형 모두 순위가 뒤지는 사람은 신입 사원이 될 수 없다 + * + * [해결 방법] + * - 먼저 하나의 유형(A)으로 오름차순 정렬 + * - A유형 1위는 무조건 뽑히니 카운트해두고, 해당 후보의 B유형 순위를 기억 + * - A유형의 순위대로 오름차순 정렬되었기에, 순위를 내려가며 B 유형의 순위가 기억해 둔 순위보다 낮은지 체크 + * - 더 낮은 경우 A유형의 윗순위자보다 B유형 역시 아랫순위라는 의미이기에 탈락 + * - 만약 B유형의 순위가 기억해둔 순위보다 높은경우, 카운트하고 기억해둔 숫자를 해당 순위로 업데이트 + * + * [시간 복잡도] + * - 정렬: O(N log N) + * - 순회: O(N) + * - 총합: O(N log N) + */ + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +public class Main { + + static void solve(int t, int[] nArr, String[][][] inputArr){ + int iter = 0; + while(t-- > 0){ + int n = nArr[iter]; + List list = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + String[] split = inputArr[iter][i]; + list.add(new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1])}); } + + list.sort(new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[0] - o2[0]; + } + }); + + int count = 0; + int state = n; + for (int i = 0; i 0) right--; // 합이 양수 → 오른쪽 포인터 줄이기 + else left++; // 합이 음수 → 왼쪽 포인터 올리기 + } + + System.out.println(ans1 + " " + ans2); + } + + public static void main(String[] args) { + solve(5, new int[]{-2, 4, -99, -1, 98}); + } +} \ No newline at end of file diff --git a/seojimin/week9/3273/Main.java b/seojimin/week9/3273/Main.java new file mode 100644 index 0000000..f43c9be --- /dev/null +++ b/seojimin/week9/3273/Main.java @@ -0,0 +1,51 @@ +/** + * 백준 3273번 - 두 수의 합 [정렬 알고리즘 유형] + *

+ * [문제 요약] + * - 수로 다른 양의 정수로 이뤄진 수열 존재 + * - 수열의 서로 다른 요소의 합이 주어진 수 x와 같은 케이스의 개수를 구하는 문제 + *

+ * [해결 방법] + * - 투 포인터 알고리즘 사용 + * - 수열을 받고, 오름차순으로 정렬해둔 뒤 적용 + * - 시작 포인터와, 끝부분 포인터를 활용 + * - 루프 조건은 시작 포인터 < 끝부분 포인터 + * - 만약 두 수의 합이 x보다 작다 -> 시작 포인터++ (숫자를 더 키워야 하기에) + * - 만약 두 수의 합이 x보다 크다 -> 끝 포인터-- (숫자를 더 줄여야 하기에) + * - 만약 두 수의 합이 x와 같다 -> 시작 포인터++, 끝 포인터-- (각자의 포인터와 맞는 쌍을 찾았기에 더이상 맞는 쌍 없음) + *

+ * [시간 복잡도] + * - 정렬: O(N log N) + * - 투 포인터 탐색: O(N) + * - 전체: O(N log N) + */ + +import java.util.Arrays; + +public class Main { + + static int solve(int n, int x, int[] nums) { + + Arrays.sort(nums); + + int count = 0; + int start = 0; + int end = n - 1; + while (start < end) { + int sum = nums[start] + nums[end]; + if (sum==x) { + count++; + start++; + end--; + } else if (sum < x) start++; + else end--; + } + + return count; + } + + public static void main(String[] args) { + int[] nums = new int[]{5, 12, 7, 10, 9, 1, 2, 3, 11}; + System.out.println(solve(9, 13, nums)); + } +} \ No newline at end of file