일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 반효경교수님
- git
- domain model
- microflow
- 매개변수 탐색
- Sort
- 멘딕스
- 완전탐색
- dfs
- lcap
- 트리
- 스택
- Recursion
- 정렬
- 집합
- 가중치없는그래프
- 자료구조
- SQL
- 해시맵
- 재귀
- 자바
- Bruteforce
- MySQL
- 그래프
- Mendix
- 이분탐색
- 백트래킹
- 프로그래머스
- algorithm
- 알고리즘
- Today
- Total
mondegreen
[240306] 알고리즘 리부트 25일차 - 백준 1920, 14425 자바 본문
[240306] 알고리즘 리부트 25일차 - 백준 1920, 14425 자바
앙갱 2024. 3. 6. 10:04import 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 m = sc.nextInt();
String[] pool = new String[n];
for (int i = 0; i < n; i++) {
pool[i] = sc.next();
}
// 이분 탐색은 정렬된 배열에서 진행 가능함
Arrays.sort(pool);
int cnt = 0;
for (int i = 0; i < m; i++) {
String thisStr = sc.next();
int l = 0;
int r = pool.length - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (pool[mid].compareTo(thisStr) < 0) {
l = mid + 1;
} else if (pool[mid].compareTo(thisStr) > 0) {
r = mid - 1;
} else {
cnt++;
break;
}
}
}
System.out.println(cnt);
}
}
[Part1-Chapter07-Clip01]
이분 탐색이란, 정렬되어 있는 집합(if i<j , a[i]<a[j])에서 원하는 값을 찾는 효율적인 탐색 방법을 말한다.
초기에 0번 idx를 L로 설정하고 배열의 마지막 원소의 인덱스를 R로 설정한 후에 두 인덱스의 중앙 idx를 M으로 설정한다. 그리고 M번째 원소의 값을 찾고자 하는 값과 비교하여 작다면 L을 M+1로 변경하고, 찾고자 하는 값보다 크다면 R을 M+1로 변경한다. 이렇게 잔존하는 배열 길의의 반씩 줄여가며 탐색을 진행하기 때문에 효율적인 탐색 알고리즘이다.
- 백준 1920 수 찾기
왜 자꾸 인덱스 오류가 나나 했더니 (l+r)/2가 아니라 l+r/2를 작성했더라. 아는 문제라고 정신 놓고 코드 치지 말자..
package BaekJoon.binarysearch;
import java.util.Arrays;
import java.util.Scanner;
public class BJ1920 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++)
arr[i] = sc.nextInt();
Arrays.sort(arr);
int m = sc.nextInt();
StringBuilder sb = new StringBuilder();
while (m-- > 0) {
int thisNum = sc.nextInt();
boolean find = false;
int l = 0;
int r = arr.length - 1;
// System.out.println("thisNum: " + thisNum);
//
// System.out.println("===================================");
while (l <= r) {
int mid = (l + r) / 2;
// System.out.println("l: " + l);
// System.out.println("r: " + r);
// System.out.println("mid: " + mid);
if (arr[mid] < thisNum) l = mid + 1;
else if (arr[mid] > thisNum) r = mid - 1;
else if (arr[mid] == thisNum) {
sb.append(1 + "\n");
find = true;
break;
}
}
if (!find) sb.append(0 + "\n");
}
System.out.println(sb);
}
}
그리고 Arrays 라이브러리에 binarySearch 함수가 있다고 해서 아래와 같이 풀어보았다. 값이 존재하지 않는 경우 return 값이 음수로 나와서 아래와 같이 조건문을 작성해서 답을 도출했다.
package BaekJoon.binarysearch;
import java.util.Arrays;
import java.util.Scanner;
public class BJ1920_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++)
arr[i] = sc.nextInt();
Arrays.sort(arr);
int m = sc.nextInt();
StringBuilder sb = new StringBuilder();
while (m-- > 0) {
int thisNum = sc.nextInt();
if (Arrays.binarySearch(arr, thisNum) >= 0) {
sb.append(1 + "\n");
} else {
sb.append(0 + "\n");
}
}
System.out.println(sb);
}
}
[Part1-Chapter07-Clip02]
- 백준 14425 문자열 집합
문자열을 한 글자씩 비교한다는 생각에 매여서 한참 돌아왔던 것 같다. 이분 탐색을 진행해야 하는데 배열 대신 어레이리스트를 원소로하는 배열을 만들어서 알파벳 순으로 분류해놓고 그 안의 문자열 길이 순으로 정렬된 어레이리스트에서 이분탐색을 진행하려고 했었다. 위에서 말한 것처럼 한글자씩 비교해야 한다는 생각에 일단 문자열의 길이가 같은 문자열의 인덱스를 찾고 인덱스를 기준으로 길이가 같은 모든 문자열을 다 순회하면서 같은 문자열인지 비교하려 했다. 그 코드가 아래코드이다. 길고 험난한 길...을 다녀왔고
package BaekJoon.binarysearch;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
public class BJ14425_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
ArrayList[] wordsPool = new ArrayList[27];
String[] targetWords = new String[m];
for (int i = 0; i < 27; i++) {
wordsPool[i] = new ArrayList<String>();
Collections.sort(wordsPool[i], (Comparator<String>) (o1, o2) -> o1.length() - o2.length());
}
for (int i = 0; i < n; i++) {
String thisStr = sc.next();
wordsPool[thisStr.charAt(0) - 97].add(thisStr);
}
for (int i = 0; i < m; i++) {
targetWords[i] = sc.next();
}
int cnt = 0;
for (int i = 0; i < m; i++) {
String thisWord = targetWords[i];
// System.out.println("thisWord: " + thisWord);
// System.out.println("thisWord.length: " + thisWord.length());
int l = 0;
int r = wordsPool[thisWord.charAt(0) - 97].size() - 1;
for (int j = 0; j < wordsPool[thisWord.charAt(0) - 97].size(); j++) {
int mid = (r + l) / 2;
// System.out.println("(0) l: "+ l);
// System.out.println("(0) r: "+ r);
// System.out.println("(0) mid: "+ mid);
if (wordsPool[thisWord.charAt(0) - 97].get(mid).toString().length() > thisWord.length()) {
r = mid - 1;
} else if (wordsPool[thisWord.charAt(0) - 97].get(mid).toString().length() < thisWord.length()) {
l = mid + 1;
} else {
if (findWord(thisWord, mid, wordsPool[thisWord.charAt(0) - 97])) {
cnt++;
break;
}
}
}
}
System.out.println(cnt);
}
private static boolean findWord(String thisWord, int mid, ArrayList wordsPool) {
boolean find = false;
for (int i = mid; i >= 0; i--) {
if (wordsPool.get(i).toString().length() < thisWord.length()) break;
if (wordsPool.get(i).equals(thisWord)) {
find = true;
break;
}
}
if (!find) {
for (int i = mid; i < wordsPool.size(); i++) {
if (wordsPool.get(i).toString().length() > thisWord.length()) break;
if (wordsPool.get(i).equals(thisWord)) {
find = true;
break;
}
}
}
if (find) return true;
else return false;
}
}
아래 코드가 정답 코드이다. String의 메서드 중 compareTo라는 메서드를 정확히 알고 있지 못했기 때문에 적용하지 못했다. 타겟 문자와 배열의 문자를 비교하면서 compareTo를 사용하면 사전식으로 비교를 진행하고 리턴값이 0과 음수 그리고 양수 세 분류로 나눠진다.
0인 경우 같은 문자라는 뜻이고, 음수인 경우 타겟 문자열 보다 비교 대상의 문자열 가 더 앞쪽에 위치해 있다는 것이며 반대로 양수인 경우 타겟 문자열 보다 비교 대상의 문자열이 더 뒤쪽에 위치한다는 의미이다. 이 부분을 활용해서 l과 r의 인덱스 위치를 조정하면 각 문자열을 직접 비교하는 로직 없이 문제를 해결할 수 있다.
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 m = sc.nextInt();
String[] pool = new String[n];
for (int i = 0; i < n; i++) {
pool[i] = sc.next();
}
// 이분 탐색은 정렬된 배열에서 진행 가능함
Arrays.sort(pool);
int cnt = 0;
for (int i = 0; i < m; i++) {
String thisStr = sc.next();
int l = 0;
int r = pool.length - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (pool[mid].compareTo(thisStr) < 0) {
l = mid + 1;
} else if (pool[mid].compareTo(thisStr) > 0) {
r = mid - 1;
} else {
cnt++;
break;
}
}
}
System.out.println(cnt);
}
}
'알고리즘 풀이 및 리뷰 > [패캠] 핵심유형 20개로 한 번에 끝내는 알고리즘 코딩테스트 리뷰' 카테고리의 다른 글
[240308] 알고리즘 리부트 27일차 - 백준 2470, 10816 자바 (0) | 2024.03.08 |
---|---|
[240307] 알고리즘 리부트 26일차 - 백준 2295 자바 (1) | 2024.03.07 |
[240305] 알고리즘 리부트 24일차 - 백준 17232 자바 (1) | 2024.03.06 |
[240301] 알고리즘 리부트 21일차 - 백준 11659, 11660, 19951 자바 (0) | 2024.03.01 |
[240229] 알고리즘 리부트 20일차 - 백준 1931 자바 (2) | 2024.02.29 |