Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions seojimin/week9/1202/Main.java
Original file line number Diff line number Diff line change
@@ -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<int[]> 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<Integer> 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}));
}
}
75 changes: 75 additions & 0 deletions seojimin/week9/1744/Main.java
Original file line number Diff line number Diff line change
@@ -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<Integer> plusList = new ArrayList<>();
List<Integer> 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}));
}
}
89 changes: 89 additions & 0 deletions seojimin/week9/1946/Main.java
Original file line number Diff line number Diff line change
@@ -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<int[]> 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<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});

int count = 0;
int state = n;
for (int i = 0; i<list.size(); i++){
int[] now = list.get(i);
if (i == 0){
count++;
state = now[1];
continue;
}
if (now[1] < state){
count++;
state = now[1];
}
}

System.out.println(count);

iter++;
}
}

public static void main(String[] args) {
int[] nArr = new int[]{5,7};
String[][] case1 = {
{"3", "2"},
{"1", "4"},
{"4", "1"},
{"2", "3"},
{"5", "5"}
};

// 테스트 케이스 2
String[][] case2 = {
{"3", "6"},
{"7", "3"},
{"4", "2"},
{"1", "4"},
{"5", "7"},
{"2", "5"},
{"6", "1"}
};

String[][][] inputArr = {case1, case2};

solve(2, nArr, inputArr);
}
}
49 changes: 49 additions & 0 deletions seojimin/week9/2470/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* 백준 2470번 - 두 용액 이름 [정렬 알고리즘]
*
* [문제 요약]
* - 양수의 산성용액과 음수의 알칼리성 용액으로 이뤄진 수열이 주어짐
* - 두 수의 합의 절댓값이 0에 최대한 가까운 두 요소를 찾아내자
*
* [해결 방법]
* - 입력받은 후 오름차순 정렬
* - 투포인터를 활용해 양쪽 끝에서 부터 이동해가며 최솟값 업데이트
*
* [시간 복잡도]
* - 정렬: O(N log N)
* - 투 포인터 탐색: O(N)
* - 전체: O(N log N)
*/

import java.util.Arrays;

public class Main {

static void solve(int n, int[] arr){
Arrays.sort(arr);

int left = 0;
int right = n - 1;
int min = Integer.MAX_VALUE;
int ans1 = 0, ans2 = 0;

while (left < right) {
int sum = arr[left] + arr[right];

if (Math.abs(sum) < min) {
min = Math.abs(sum);
ans1 = arr[left];
ans2 = arr[right];
}

if (sum > 0) right--; // 합이 양수 → 오른쪽 포인터 줄이기
else left++; // 합이 음수 → 왼쪽 포인터 올리기
}

System.out.println(ans1 + " " + ans2);
}

public static void main(String[] args) {
solve(5, new int[]{-2, 4, -99, -1, 98});
}
}
51 changes: 51 additions & 0 deletions seojimin/week9/3273/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* 백준 3273번 - 두 수의 합 [정렬 알고리즘 유형]
* <p>
* [문제 요약]
* - 수로 다른 양의 정수로 이뤄진 수열 존재
* - 수열의 서로 다른 요소의 합이 주어진 수 x와 같은 케이스의 개수를 구하는 문제
* <p>
* [해결 방법]
* - 투 포인터 알고리즘 사용
* - 수열을 받고, 오름차순으로 정렬해둔 뒤 적용
* - 시작 포인터와, 끝부분 포인터를 활용
* - 루프 조건은 시작 포인터 < 끝부분 포인터
* - 만약 두 수의 합이 x보다 작다 -> 시작 포인터++ (숫자를 더 키워야 하기에)
* - 만약 두 수의 합이 x보다 크다 -> 끝 포인터-- (숫자를 더 줄여야 하기에)
* - 만약 두 수의 합이 x와 같다 -> 시작 포인터++, 끝 포인터-- (각자의 포인터와 맞는 쌍을 찾았기에 더이상 맞는 쌍 없음)
* <p>
* [시간 복잡도]
* - 정렬: 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));
}
}