728x90
해당 문제를 풀 때 다음과 같이 접근했다.
1. 매일 매일 산에 오를 때마다 가장 큰 것을 자르면 어떨까? -> 테케에 맞지 않는다.
2. 나무가 자라는 게 등차 수열이네 -> 그러면 공차의 오름차순 대로 나무를 잘라볼까? -> 테케 맞음
3. 그러면 오름차순 정렬할 때 Arrays.sort를 쓸까?
4. 어차피 계속 배열을 유지할 필욘 없으니 PriorityQueue를 써볼까?
라는 의식흐름에서 나온게 다음과 같은 코드이다.
-> 하지만 함정이 숨어 있었다...흑흑
다름아닌 데이터 타입...
최악의 상황을 가정해 보았다.
나무 100,000개에 등차가 10,000이고 첫항이 전부 100,000 일 경우
99999*100000/2*10000 + 100000 = 49,999,500,100,000 => long으로 선언해야함
long = +-9,223,372,036,854,775,807 / int +- = 2,147,483,647 이므로 long 타입으로 total 변수를 선언했어야 했다.
소스코드는 우선순위큐(최소힙)과 배열로 푼 방식 둘다 구현해봤다.
삼성 SW 역량 테스트 B형을 치른지 3일? 됐는데 아직 자료구조, 데이터 타입의 중요성을 까먹은 것인가?
설계에 더욱 더 공을 들이자!
항상 최악의 경우를 테스트 해보자!
package boj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Boj_14247 {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
long total = 0;
// 나무 100,000개에 공차가 10,000이고 첫항이 전부 100,000 일 경우 99999*100000/2*10000 + 100000 = 49,999,500,100,000 => long으로 선언해야함
// long = +-9,223,372,036,854,775,807, int +- = 2,147,483,647
// 배열, 연결리스트로 구현한다면 삭제 O(1), 삽입(n)
// 우선순위 큐의 경우 삭제, 삽입 O(log2n); n= 100000기준 32
// Arrays.sort의 경우 dualPivotQuicksort : 평균 O(nlogn) 최악:O(n^2) 100000 기준 평균 1600000
// Collections.sort의 경우 Timsort : 평균 O(nlogn) 최악:O(n^2) n = 100000 기준 평균 1600000
// 한 번의 정렬을 하여 사용하여야 하며 데이터가 지속적으로 필요하지 않으므로 우선순위 큐를 사용한다.
PriorityQueue<Integer> pq = new PriorityQueue<>();
StringTokenizer stz = new StringTokenizer(br.readLine());
// 각 나무의 상수 부분은 미리 더해줘도 된다. 결국 공차의 오름차순 대로 나무를 자르게 될 것이다.
for (int i = 0; i < n; i++) {
total += Integer.parseInt(stz.nextToken());
}
stz = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
pq.add(Integer.parseInt(stz.nextToken()));
}
// 우선순위 큐의 경우 객체 생성시 Collections.reverseOrder()을 파라미터로 넘겨주면 내림차순으로 정렬된다.
for (int i = 0; i < n; i++) {
total += i*pq.poll(); // 첫째날부터 자른다고 한다면 n은 0부터 시작한다.
}
System.out.println(total);
// 배열 version
int tree[] = new int[n];
StringTokenizer stz2 = new StringTokenizer(br.readLine());
// 각 나무의 상수 부분은 미리 더해줘도 된다. 결국 공차의 오름차순 대로 나무를 자르게 될 것이다.
for (int i = 0; i < n; i++) {
total += Integer.parseInt(stz2.nextToken());
}
stz2 = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
tree[i] = Integer.parseInt(stz2.nextToken());
}
Arrays.sort(tree);
for (int i = 0; i < n; i++) {
total += i*tree[i]; // 첫째날부터 자른다고 한다면 n은 0부터 시작한다.
}
System.out.println(total);
}
}
728x90
'알고리즘공부(Algorithm Study) > 문제풀이(ProblemSolving)' 카테고리의 다른 글
백준 2579 - 계단 오르기 JAVA (2) | 2022.03.27 |
---|---|
백준 1932 - 정수 삼각형 JAVA (0) | 2022.03.26 |
백준 9251 - LCS JAVA (0) | 2022.03.24 |
백준 1149 - RGB거리 JAVA (0) | 2022.03.23 |
백준 1600 말이 되고픈 원숭이 - JAVA (0) | 2022.03.20 |
댓글