Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준
- 백준1253
- 백준_구간합구하기
- 백준2751
- 백준11724
- 자바
- 백준1260
- 백준1874
- 버블소트
- 백준11399
- 구간합
- 백준11720
- Java
- 정렬알고리즘
- 백준_11659
- 백준1546
- 백준10998
- 백준1377
- 백준1940
- 백준1427
- 백준2023
- 백준11286
- 백준1517
- 백준12891
- 백준2750
- stack
- 백준13023
- 백준17298
- 백준11003
- 백준2018
Archives
- Today
- Total
HOONDOC
[백준]1253 좋다 - 자바/Java 본문
1253번: 좋다
풀이
💡 메모리 18528KB, 시간 288ms
- 이중 포문까지만 가능, 삼중 포문 부터는 시간 초과가 날 것이다.
- 입력되는 값의 범위가 -10억~10억이고 Integer의 범위가 -20억~20억이므로 두 수의 합은 안전하게 Long 타입으로 가져갔다.이 때 검사할 숫자들은 정렬된 상태여야 한다. 정렬된 값들에만 적용 가능하다.
- 핵심은 검사할 숫자를 정하고, 해당 숫자를 기준으로 투포인터 알고리즘을 적용하는 것이다.
- 투포인터 알고리즘 구현에 익숙해져가는 것 같다.
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] numb = new int[N];
for(int i = 0; i<N; i++) numb[i] = sc.nextInt();
Arrays.sort(numb);
int cnt = 0;
for(int i = 0; i<N; i++) {
int find = numb[i]; // 검사할 숫자
int stIdx = 0;
int edIdx = N-1;
while(stIdx < edIdx) { // 투포인터 알고리즘
long sum = numb[stIdx] + numb[edIdx];
if(sum == find) { // 각 숫자가 find와 같은 수면 안됨
if(stIdx != i && edIdx != i) {
cnt++; // 다른 위치의 숫자일때만 가산
break;
}
else if(stIdx == i) stIdx++;
else if(edIdx == i) edIdx--;
}
else if(sum < find) stIdx++;
else edIdx--;
}
}
System.out.print(cnt);
sc.close();
}
}
코드 리뷰
- 입력을 받을 때 BufferedReader를 사용했음에도 시간이 많이 사용되었다.
- findGood 함수는 입력된 숫자의 배열 A와 검사하고자 하는 값의 인덱스 번호를 받는다. 좋은 수라면 1을 반환하고, 아니라면 0을 반환한다.이는 자바에서 정수는 Primitive Type이기 때문이다. Primitive Type은 객체를 호출할 때 복제되어 전달되는 게 아니라, 주소값을 전달한다.
- Integer형 배열은 호출될 때 주소값을 반환한다. 즉 findGood 함수에서 A[]를 받아도 배열이 무한정 복제되어 사용되는게 아니라, 하나의 배열의 주소값을 받아 사용하는 일종의 공유 데이터다.
- 근데 왜 시간이 2384ms가 나왔지? 함수를 호출할 때 시간이 그렇게 오래 걸리나..?
💡 풀이자 : gi0204, 메모리 : 14640KB, 시간 2384ms
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());
int N = Integer.parseInt(stringTokenizer.nextToken());
int[] A = new int[N];
stringTokenizer = new StringTokenizer(bufferedReader.readLine());
for (int i = 0; i < N; i++) {
A[i] = Integer.parseInt(stringTokenizer.nextToken());
}
int good = 0;
for (int i = 0; i < N; i++) {
good += findGood(A, i);
}
System.out.println(good);
}
public static int findGood(int[] A, int idx) {
int num = A[idx];
for (int i = 0; i < A.length; i++) {
if (i == idx) {
continue;
}
for (int j = i + 1; j < A.length; j++) {
if (j == idx) {
continue;
}
if (A[i] + A[j] == num) {
return 1;
}
}
}
return 0;
}
}
- 해당 풀이는 나랑 완전히 똑같다. 배열을 선언할 때 타입 지정만 다르다.
💡 풀이자 : spparty 메모리 : 22232KB, 시간 408ms
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
long arr[] = new long[N];
for (int i=0; i<N; i++)
{
arr[i] = sc.nextLong();
}
Arrays.sort(arr);
int cnt=0;
for (int i=0; i<N; i++)
{
int left=0;
int right = N-1;
while (left < right)
{
if (left == i)
{
left++;
continue;
}
else if (right == i)
{
right--;
continue;
}
if (arr[left] + arr[right] == arr[i])
{
cnt++;
break;
}
else if (arr[left] + arr[right] < arr[i])
{
left++;
}
else if (arr[left] + arr[right] > arr[i])
{
right--;
}
}
}
System.out.println(cnt);
}
}
- 얘도 로직은 똑같다. 입력받을 때 BufferedReader를 사용하여 시간이 단축됐다.
💡 풀이자 : jjjp9966 메모리 : 12792KB, 시간 124ms
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] nums = new int[N];
int count = 0; // 좋은 수의 개수
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
nums[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(nums);
for (int i = 0; i < N; i++) {
int startIdx = 0;
int endIdx = N - 1;
while (startIdx < endIdx) {
int sum = nums[startIdx] + nums[endIdx];
if (sum == nums[i]) {
if (startIdx != i && endIdx != i) {
count++;
break;
} else if (startIdx == i) {
startIdx++;
} else if (endIdx == i) {
endIdx--;
}
} else if (sum < nums[i]) {
startIdx++;
} else {
endIdx--;
}
}
}
System.out.println(count);
}
}
Conclusion
- 이 문제는 풀이가 거의 정형화 되어있는 것 같다. 약간 응용된 투포인터 알고리즘.
- 자바에서 Primitive Type를 어떻게 취급하고 종류는 무엇인지 다시 한 번 정리해야겠다. 첫번째 풀이자의 코드가 왜 그렇게 시간이 오래 걸렸는지 알고싶다.
'문제 풀이 > BAEKJOON' 카테고리의 다른 글
[백준]11003 최솟값 찾기 - 자바/Java (2) | 2022.12.30 |
---|---|
[백준]12891 DNA 비밀번호 - 자바/Java (0) | 2022.12.29 |
[백준]1940 주몽 - 자바/Java (0) | 2022.12.29 |
[백준]2018 수들의 합5 - 자바/Java (0) | 2022.12.28 |
[백준]11720 숫자의 합 - Java/자바 (0) | 2022.12.28 |