일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- HashMap
- Java
- 백준 2467번 용액 자바 - 이분탐색
- 백준 1806번 부분합 java
- hash
- 백준 1541
- 프로그래머스 자바
- 프로그래머스
- 백준 1197번 최소 스패닝 트리 - java
- toUpperCase
- 백준 3190번
- 백준 1647번 도시 분할 계획 - java
- 최소 힙 1927
- 백준 1043번 거짓말 - java 분리 집합
- 백준 14938번 서강그라운드
- 코틀린기초
- 18111번 마인크래프트 - java 구현
- map
- mysql hy000 에러
- Stack
- dp
- StringBuilder
- HashSet
- append
- ac 5430번
- 프로그래머스 java
- replace()
- kotlin
- 백준 2473번 세 용액 - java
- StringTokenizer
- Today
- Total
말하는 컴공감자의 텃밭
백준 10815번 숫자카드 <실버5> - 자바 java 이분탐색, HashSet 본문
문제는 간단하다. 네번째 줄에 주어지는 숫자들이 두번째 줄에 주어진 숫자였다면 해당 위치에 1, 아니라면 0을 반환하면 되는 문제다.
다만 입력값 범위가 굉장히 크기에 시간복잡도 O(n) 관리가 필요하다.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { // Input Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int[] N_arr = new int[N]; for (int i = 0; i < N; i++) { // 두번째줄 배열에 넣기 N_arr[i] = sc.nextInt(); } int M = sc.nextInt(); int[] M_arr = new int[M]; for (int i = 0; i < M; i++) { // 네번째줄 배열에 넣기 M_arr[i] = sc.nextInt(); } int[] answer = new int[M]; Arrays.sort(N_arr); // 이분 탐색을 위해 N 배열 정렬 // Logic for (int i = 0; i < M_arr.length; i++) { answer[i] = BS(N_arr, M_arr[i]) ? 1 : 0; // 이분탐색 호출 } for (int s : answer) { System.out.printf("%d ", s); } sc.close(); } // Binary Search public static boolean BS(int[] arr, int n) { int left = 0; int right = arr.length - 1; int mid; while (left <= right) { // left # # mid # # right 처럼 mid의 값으로 mid = (left + right) / 2; if (arr[mid] < n) { left = mid + 1; // 중앙값이 찾는 값보다 작다면, 왼쪽 조여주기 } else if (arr[mid] > n) { // 크다면 오른쪽 조여주기. right = mid - 1; } else { // 같다면 true return true; } } return false; // 없다면 false } } | cs |
초기에 이분탐색을 사용해서 작성한 코드이다,
이분탐색은 하나 하나 탐색하는 방법보다 성능이 좋으므로 해결될거라 생각했다.
ㅋㅋㅎ 퇴근하고 더워서 녹은 몸으로 작성해서 틀려도 별 생각이 없었다.
문제를 한번 더 읽고 그냥 당연하게 HashSet으로 작성해버렸다.
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 32 33 34 | import java.util.HashSet; import java.util.Scanner; public class Main { public static void main(String[] args) { // Input Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int[] N_arr = new int[N]; HashSet<Integer> N_set = new HashSet<>(); for (int i = 0; i < N; i++) { N_arr[i] = sc.nextInt(); N_set.add(N_arr[i]); } int M = sc.nextInt(); int[] M_arr = new int[M]; for (int i = 0; i < M; i++) { M_arr[i] = sc.nextInt(); } sc.close(); // Logic for (int i = 0; i < M_arr.length; i++) { if (N_set.contains(M_arr[i])) { System.out.print("1 "); } else { System.out.print("0 "); } } } } | cs |
간결하고, 배열을 정렬 할 필요도 없다. 단순히 값이 있는지만 해싱하기 때문에.
시간 복잡도를 비교해보면
이진 검색 방식:
첫 번째 배열 정렬(N_arr): O(N log N)
두 번째 배열(M_arr)의 각 요소에 대한 이진 검색 수행: O(M log N)
총 시간 복잡도: O((N + M) log N)
이진 검색 방식은 N_arr sort가 필요했고, 정렬에는 O(N log N)이 필요했다.
M 요소에 대한 이진 탐색에는 O(M log N)이 필요하다. 따라서 전체 시간 복잡도는 O((N + M) log N)
해시셋 접근법:
첫 번째 배열에 대한 HashSet 빌드(N_arr): O(N)
두 번째 배열(M_arr)의 각 요소에 대한 조회 수행: O(M)
총 시간 복잡도: O(N + M)
HashSet은 HashSet 생성에 O(N) 시간이 걸리고, 두 번째 배열의 각 요소에 대한 조회를 수행하는 데 O(M) 시간이 걸린다.
HashSet은 조회 작업에 대해 O(1) 평균 시간 복잡도를 제공하므로 전체 시간 복잡도는 O(N + M)이다.
아직도 자료구조가 많이 부족한거같다.. 실질적으로 쓰고있는거만 쓰고, 아직 어려운 문제를 많이 접하지 않아서 단순하게만 푸려는 경향이 있는 듯 싶다. 오히려 쉬운문제에 쓸때없이 많이 어렵게 생각할때도 있고
개념적으로 공부를 더 하고, 혼자서는 못 풀어도 골드 문제를 노려봐서 내가 생각하는 방향이랑 문제에서 제시하는 방향이랑 맞는지 비교하면서 부족함을 채워야겠다.
'알고리즘 > Backjoon - Java' 카테고리의 다른 글
백준 25192 인사성 밝은 곰곰이 <S4> - java HashSet (0) | 2023.10.01 |
---|---|
백준 29774 케이크 자르기 게임 (small) - java 에드훅 (0) | 2023.09.15 |
백준 13335 트럭 <실버 1> - 자바 Queue (0) | 2023.07.20 |
백준 1152 단어의 개수 <브론즈 2> - 자바 StringTokenizer (0) | 2023.07.18 |
백준 28278 스택2 <실버4> - 자바 Stack (0) | 2023.07.13 |