From 448d3151de8f34878265a4d053cacee5eddce299 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Wed, 9 Sep 2020 14:47:37 +0900 Subject: [PATCH 01/68] Update 2.py --- 15/2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/2.py b/15/2.py index 724373a..86e85ef 100644 --- a/15/2.py +++ b/15/2.py @@ -1,4 +1,4 @@ -# 이진 탐색 소스코드 구현 (재귀 함수) +# 이진 탐색 소스코드 구현(재귀 함수) def binary_search(array, start, end): if start > end: return None From 5da91338f247119e175940b2c24f3ac89d27c9bb Mon Sep 17 00:00:00 2001 From: ndb796 Date: Wed, 9 Sep 2020 15:03:19 +0900 Subject: [PATCH 02/68] Update --- 15/2.cpp | 33 ++++++++++++++++++++++++++++++ 15/3.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++ 15/4.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/15/2.cpp b/15/2.cpp index e69de29..7a85f52 100644 --- a/15/2.cpp +++ b/15/2.cpp @@ -0,0 +1,33 @@ +#include + +using namespace std; + +// 이진 탐색 소스코드 구현(재귀 함수) +int binarySearch(vector& arr, int start, int end) { + if (start > end) return -1; + int mid = (start + end) / 2; + // 고정점을 찾은 경우 중간점 인덱스 반환 + if (arr[mid] == mid) return mid; + // 중간점의 값보다 중간점이 작은 경우 왼쪽 확인 + else if (arr[mid] > mid) return binarySearch(arr, start, mid - 1); + // 중간점의 값보다 중간점이 큰 경우 오른쪽 확인 + else return binarySearch(arr, mid + 1, end); +} + +int n; +vector arr; + +int main(void) { + cin >> n; + for (int i = 0; i < n; i++) { + int x; + cin >> x; + arr.push_back(x); + } + + // 이진 탐색(Binary Search) 수행 + int index = binarySearch(arr, 0, n - 1); + + // 결과 출력 + cout << index << '\n'; +} \ No newline at end of file diff --git a/15/3.cpp b/15/3.cpp index e69de29..dc7226f 100644 --- a/15/3.cpp +++ b/15/3.cpp @@ -0,0 +1,49 @@ +#include + +using namespace std; + +// 집의 개수(N)와 공유기의 개수(C) +int n, c; +vector arr; + +int main() { + cin >> n >> c; + + // 전체 집의 좌표 정보를 입력 받기 + for (int i = 0; i < n; i++) { + int x; + cin >> x; + arr.push_back(x); + } + // 이진 탐색 수행을 위해 정렬 수행 + sort(arr.begin(), arr.end()); + + int start = arr[1] - arr[0]; // 집의 좌표 중에 가장 작은 값 + int end = arr[n - 1] - arr[0]; // 집의 좌표 값 중에서 가장 큰 값 + int result = 0; + + while (start <= end) { + // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + int mid = (start + end) / 2; + int value = arr[0]; + int cnt = 1; + // 현재의 mid 값을 이용해 공유기를 설치하기 + for (int i = 1; i < n; i++) { // 앞에서부터 차근차근 설치 + if (arr[i] >= value + mid) { + value = arr[i]; + cnt += 1; + } + } + // C개 이상의 공유기를 설치할 수 있는 경우, 거리를 증가시키기 + if (cnt >= c) { + start = mid + 1; + result = mid; // 최적의 결과를 저장 + } + // C개 이상의 공유기를 설치할 수 없는 경우, 거리를 감소시키기 + else { + end = mid - 1; + } + } + + cout << result << '\n'; +} \ No newline at end of file diff --git a/15/4.cpp b/15/4.cpp index e69de29..1a20140 100644 --- a/15/4.cpp +++ b/15/4.cpp @@ -0,0 +1,61 @@ +#include + +using namespace std; + +// 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 +int countByRange(vector& v, string leftValue, string rightValue) { + vector::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue); + vector::iterator leftIndex = lower_bound(v.begin(), v.end(), leftValue); + return rightIndex - leftIndex; +} + +// 문자열 내에서 특정한 문자열을 다른 문자열로 모두 치환하는 함수 +string replaceAll(string str, string from, string to){ + string res = str; + int pos = 0; + while((pos = res.find(from, pos)) != string::npos) + { + res.replace(pos, from.size(), to); + pos += to.size(); + } + return res; +} + +// 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트 +vector arr[10001]; +// 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트 +vector reversed_arr[10001]; + +vector solution(vector words, vector queries) { + vector answer; + + // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입 + for (int i = 0; i < words.size(); i++) { + string word = words[i]; + arr[word.size()].push_back(word); // 단어를 삽입 + reverse(word.begin(), word.end()); + reversed_arr[word.size()].push_back(word); // 단어를 뒤집어서 삽입 + } + + // 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행 + for (int i = 0; i < 10001; i++) { + sort(arr[i].begin(), arr[i].end()); + sort(reversed_arr[i].begin(), reversed_arr[i].end()); + } + + // 쿼리를 하나씩 확인하며 처리 + for (int i = 0; i < queries.size(); i++) { + string q = queries[i]; + int res = 0; + if (q[0] != '?') { // 접미사에 와일드 카드가 붙은 경우 + res = countByRange(arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z")); + } + else { // 접두사에 와일드 카드가 붙은 경우 + reverse(q.begin(), q.end()); + res = countByRange(reversed_arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z")); + } + // 검색된 단어의 개수를 저장 + answer.push_back(res); + } + return answer; +} \ No newline at end of file From c511239ff8ec0c270b48c61d3363f359baa8bb0a Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Wed, 9 Sep 2020 15:06:55 +0900 Subject: [PATCH 03/68] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 08f93ad..c0e96ca 100644 --- a/README.md +++ b/README.md @@ -197,10 +197,10 @@ #### 15장 이진 탐색 -* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): [Python 3.7 코드](/15/1.py) -* 고정점 찾기 (Amazon 인터뷰 기출): [Python 3.7 코드](/15/2.py) -* [공유기 설치](https://www.acmicpc.net/problem/2110) (핵심 유형): [Python 3.7 코드](/15/3.py) -* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): [Python 3.7 코드](/15/4.py) +* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): ([Python 3.7 코드](/15/1.py) / [C++ 코드](/15/1.cpp)) +* 고정점 찾기 (Amazon 인터뷰 기출): ([Python 3.7 코드](/15/2.py) / [C++ 코드](/15/2.cpp)) +* [공유기 설치](https://www.acmicpc.net/problem/2110) (핵심 유형): ([Python 3.7 코드](/15/3.py) / [C++ 코드](/15/3.cpp)) +* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): ([Python 3.7 코드](/15/4.py) / [C++ 코드](/15/4.cpp)) #### 16장 다이나믹 프로그래밍 From 41ed0033836d4cb8f756bbdfea136cb375d07ad7 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Thu, 10 Sep 2020 02:57:37 +0900 Subject: [PATCH 04/68] Create 5_notice.md --- 16/5_notice.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 16/5_notice.md diff --git a/16/5_notice.md b/16/5_notice.md new file mode 100644 index 0000000..5b5e3bb --- /dev/null +++ b/16/5_notice.md @@ -0,0 +1,15 @@ +예를 들어 먼저 못생긴 수로 1이 있다고 해보자. 이때 각각 2의 배수, 3의 배수, 5의 배수를 구하면 다음과 같다. + +* 2의 배수: 1 X 2 = 2 +* 3의 배수: 1 X 3 = 3 +* 5의 배수: 1 X 5 = 5 + +이로써 우리는 새롭게 2, 3, 5 또한 못생긴 수에 해당한다는 것을 알 수 있다. 따라서 이를 고려했을때, 전체 못생긴 수는 {1, 2, 3, 5}가 된다. + +첫 번째로 못생긴 수인 1에 이어서 그다음으로 못생긴 수는 2가 된다. 이때 각각 2의 배수, 3의 배수, 5의 배수를 구하면 다음과 같다. + +* 2의 배수: 2 X 2 = 4 +* 3의 배수: 2 X 3 = 6 +* 5의 배수: 2 X 5 = 10 + +이로써 우리는 4, 6, 10이 못생긴 수에 해당한다는 것을 알 수 있다. 따라서 이를 고려했을 때, 전체 못생긴 수는 {1, 2, 3, 4, 5, 6, 10}이 된다. 이렇게 못생긴 수들을 작은 수부터 차례대로 확인하면서, 각 못생긴 수에 대해서 2의 배수, 3의 배수, 5의 배수를 고려한다는 점을 기억하여 효율적으로 소스코드를 작성하면 다음과 같이 작성할 수 있다. From 615a852b84d68f2e1743b8e7de32c28c40008a12 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Thu, 10 Sep 2020 03:01:39 +0900 Subject: [PATCH 05/68] Update notice.md --- notice.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notice.md b/notice.md index e837e84..8e40f14 100644 --- a/notice.md +++ b/notice.md @@ -63,3 +63,7 @@ * \[Step 2\]의 내용은 다음과 같이 변경되어야 올바른 내용입니다. > 전체 남은 시간은 3초이고, 이번 단계에서는 2번 음식을 빼야 한다. 전체 음식이 2개 남아 있으므로 이번 단계에서 뺄 시간은 2(남은 음식의 개수) X 2(2번 음식을 다 먹는 시간) = 4초가 된다. 하지만 현재 전체 남은 시간이 3초인데, 이는 4보다 작으므로 빼지 않도록 한다. + +#### (570p) 예시 설명 + +* 문제 해설의 예시 설명에 오류가 있습니다. 올바른 설명은 [수정 사항이 반영된 설명 링크](https://github.com/ndb796/python-for-coding-test/blob/master/16/5_notice.md)와 같습니다. From 518e9781db50e5b2728d3658d4148aae85e2f66b Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Thu, 17 Sep 2020 14:03:12 +0900 Subject: [PATCH 06/68] Update notice.md --- notice.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notice.md b/notice.md index 8e40f14..c614182 100644 --- a/notice.md +++ b/notice.md @@ -25,6 +25,10 @@ * 그림 ⓑ에서 그림의 오른쪽 부분은 '털 수 있음'인데 잘못 기재되어 있습니다. +#### (226p) 출력 조건 오탈자 + +* 출력 조건으로 "첫째 줄에 M 원을 만들기 위한 최소한의 화폐 개수를 출력한다."가 올바른 내용입니다. + #### (263p) 주석 오탈자 * 주석에서 "# x번 노드에서 y번 노드로 가는 비용이 z라는 의미"가 올바른 내용입니다. From 06a1d38c902bc031928751ca8dcdca1ebf6959de Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 18 Sep 2020 11:18:51 +0900 Subject: [PATCH 07/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0e96ca..9e26cb9 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,7 @@ ### Part 4 부록 -#### 부록 A 코딩 테스트를 위한파이썬 문법 +#### 부록 A 코딩 테스트를 위한 파이썬 문법 * 자료형 * 수 자료형 From f52578c8c2b643877c735d9841f3101eaafef1e2 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 20:49:17 +0900 Subject: [PATCH 08/68] Create 1.cpp --- 20/1.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 20/1.cpp diff --git a/20/1.cpp b/20/1.cpp new file mode 100644 index 0000000..58aeb84 --- /dev/null +++ b/20/1.cpp @@ -0,0 +1,20 @@ +#include + +using namespace std; + +// 소수 판별 함수(2이상의 자연수에 대하여) +bool isPrimeNumber(int x) { + // 2부터 x의 제곱근까지의 모든 수를 확인하며 + for (int i = 2; i <= (int) sqrt(x); i++) { + // x가 해당 수로 나누어떨어진다면 + if (x % i == 0) { + return false; // 소수가 아님 + } + } + return true; // 소수임 +} + +int main() { + cout << isPrimeNumber(4) << '\n'; + cout << isPrimeNumber(7) << '\n'; +} From d9eb689cc73372fb62fd5ea0bcb2d4fb7fc720e3 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 20:49:35 +0900 Subject: [PATCH 09/68] Create 1.java --- 20/1.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 20/1.java diff --git a/20/1.java b/20/1.java new file mode 100644 index 0000000..34e1865 --- /dev/null +++ b/20/1.java @@ -0,0 +1,20 @@ +import java.util.*; + +class Main { + // 소수 판별 함수(2이상의 자연수에 대하여) + public static boolean isPrimeNumber(int x) { + // 2부터 x의 제곱근까지의 모든 수를 확인하며 + for (int i = 2; i <= Math.sqrt(x); i++) { + // x가 해당 수로 나누어떨어진다면 + if (x % i == 0) { + return false; // 소수가 아님 + } + } + return true; // 소수임 + } + + public static void main(String[] args) { + System.out.println(isPrimeNumber(4)); + System.out.println(isPrimeNumber(7)); + } +} From ea19bc39b762adaafca330447e78b8952980ebac Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:00:56 +0900 Subject: [PATCH 10/68] Create 2.cpp --- 20/2.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 20/2.cpp diff --git a/20/2.cpp b/20/2.cpp new file mode 100644 index 0000000..07be191 --- /dev/null +++ b/20/2.cpp @@ -0,0 +1,27 @@ +#include + +using namespace std; + +int n = 1000; // 2부터 1,000까지의 모든 수에 대하여 소수 판별 +// 처음엔 모든 수가 소수(True)인 것으로 초기화(0과 1은 제외) +vector arr(n + 1, true); + +int main() { + // 에라토스테네스의 체 알고리즘 수행 + // 2부터 n의 제곱근까지의 모든 수를 확인하며 + for (int i = 2; i <= (int) sqrt(n); i++) { + // i가 소수인 경우(남은 수인 경우) + if (arr[i] == true) { + // i를 제외한 i의 모든 배수를 지우기 + int j = 2; + while (i * j <= n) { + arr[i * j] = false; + j += 1; + } + } + } + // 모든 소수 출력 + for (int i = 2; i <= n; i++) { + if (arr[i]) cout << i << ' '; + } +} From d3fcf11d38f3d674c1d4d3b6b5f15cf91331d7ff Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:06:28 +0900 Subject: [PATCH 11/68] Create 2.java --- 20/2.java | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 20/2.java diff --git a/20/2.java b/20/2.java new file mode 100644 index 0000000..71b2dde --- /dev/null +++ b/20/2.java @@ -0,0 +1,27 @@ +import java.util.*; + +class Main { + public static int n = 1000; // 2부터 1,000까지의 모든 수에 대하여 소수 판별 + public static boolean[] arr = new boolean[n + 1]; + + public static void main(String[] args) { + Arrays.fill(arr, true); // 처음엔 모든 수가 소수(True)인 것으로 초기화(0과 1은 제외) + // 에라토스테네스의 체 알고리즘 수행 + // 2부터 n의 제곱근까지의 모든 수를 확인하며 + for (int i = 2; i <= Math.sqrt(n); i++) { + // i가 소수인 경우(남은 수인 경우) + if (arr[i] == true) { + // i를 제외한 i의 모든 배수를 지우기 + int j = 2; + while (i * j <= n) { + arr[i * j] = false; + j += 1; + } + } + } + // 모든 소수 출력 + for (int i = 2; i <= n; i++) { + if (arr[i]) System.out.print(i + " "); + } + } +} From 7ad989b82447290762723373d8fdb184eea96887 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:23:44 +0900 Subject: [PATCH 12/68] Create 3.cpp --- 20/3.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 20/3.cpp diff --git a/20/3.cpp b/20/3.cpp new file mode 100644 index 0000000..ecdc566 --- /dev/null +++ b/20/3.cpp @@ -0,0 +1,29 @@ +#include + +using namespace std; + +int n = 5; // 데이터의 개수 N +int m = 5; // 찾고자 하는 부분합 M +int arr[] = {1, 2, 3, 2, 5}; // 전체 수열 + +int main() { + int cnt = 0; + int intervalSum = 0; + int end = 0; + + // start를 차례대로 증가시키며 반복 + for (int start = 0; start < n; start++) { + // end를 가능한 만큼 이동시키기 + while (intervalSum < m && end < n) { + intervalSum += arr[end]; + end += 1; + } + // 부분합이 m일 때 카운트 증가 + if (intervalSum == m) { + cnt += 1; + } + intervalSum -= arr[start]; + } + + cout << cnt << '\n'; +} From df01d140b825ea843ca06e69ac7d0e9fedf59ca8 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:29:48 +0900 Subject: [PATCH 13/68] Create 3.java --- 20/3.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 20/3.java diff --git a/20/3.java b/20/3.java new file mode 100644 index 0000000..eb610d4 --- /dev/null +++ b/20/3.java @@ -0,0 +1,29 @@ +import java.util.*; + +class Main { + public static int n = 5; // 데이터의 개수 N + public static int m = 5; // 찾고자 하는 부분합 M + public static int[] arr = {1, 2, 3, 2, 5}; // 전체 수열 + + public static void main(String[] args) { + int cnt = 0; + int intervalSum = 0; + int end = 0; + + // start를 차례대로 증가시키며 반복 + for (int start = 0; start < n; start++) { + // end를 가능한 만큼 이동시키기 + while (intervalSum < m && end < n) { + intervalSum += arr[end]; + end += 1; + } + // 부분합이 m일 때 카운트 증가 + if (intervalSum == m) { + cnt += 1; + } + intervalSum -= arr[start]; + } + + System.out.println(cnt); + } +} From c1c692baf2aaac75e1da71cb9b8fc3e3f07dae52 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:55:35 +0900 Subject: [PATCH 14/68] Create 5.cpp --- 20/5.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 20/5.cpp diff --git a/20/5.cpp b/20/5.cpp new file mode 100644 index 0000000..fbeaed8 --- /dev/null +++ b/20/5.cpp @@ -0,0 +1,22 @@ +#include + +using namespace std; + +int n = 5; // 데이터의 개수 N과 데이터 입력받기 +int arr[] = {10, 20, 30, 40, 50}; +int prefixSum[6]; + +int main() { + // 접두사 합(Prefix Sum) 배열 계산 + int sumValue = 0; + + for (int i = 0; i < n; i++) { + sumValue += arr[i]; + prefixSum[i + 1] = sumValue; + } + + // 구간 합 계산(세 번째 수부터 네 번째 수까지) + int left = 3; + int right = 4; + cout << prefixSum[right] - prefixSum[left - 1] << '\n'; +} From 79b1f96473587088c2b4d6cc7e71dd7a45638252 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:56:05 +0900 Subject: [PATCH 15/68] Create 5.java --- 20/5.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 20/5.java diff --git a/20/5.java b/20/5.java new file mode 100644 index 0000000..a0b2fcc --- /dev/null +++ b/20/5.java @@ -0,0 +1,22 @@ +import java.util.*; + +class Main { + public static int n = 5; // 데이터의 개수 N과 데이터 입력받기 + public static int arr[] = {10, 20, 30, 40, 50}; + public static int[] prefixSum = new int[6]; + + public static void main(String[] args) { + // 접두사 합(Prefix Sum) 배열 계산 + int sumValue = 0; + + for (int i = 0; i < n; i++) { + sumValue += arr[i]; + prefixSum[i + 1] = sumValue; + } + + // 구간 합 계산(세 번째 수부터 네 번째 수까지) + int left = 3; + int right = 4; + System.out.println(prefixSum[right] - prefixSum[left - 1]); + } +} From ebc60b43e2cec47b48575c38af6fcd87c0de1a3f Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 3 Oct 2020 21:59:43 +0900 Subject: [PATCH 16/68] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9e26cb9..51e3822 100644 --- a/README.md +++ b/README.md @@ -296,11 +296,11 @@ #### 부록 B 기타 알고리즘 * 이론 - * 소수 판별: [Python 3.7 코드](/20/1.py) - * 에라토스테네스의 체: [Python 3.7 코드](/20/2.py) - * 특정한 합을 가지는 부분 연속 수열 찾기 (투 포인터): [Python 3.7 코드](/20/3.py) + * 소수 판별: ([Python 3.7 코드](/20/1.py) / [C++ 코드](/20/1.cpp) / [Java 코드](/20/1.java)) + * 에라토스테네스의 체: ([Python 3.7 코드](/20/2.py) / [C++ 코드](/20/2.cpp) / [Java 코드](/20/2.java)) + * 특정한 합을 가지는 부분 연속 수열 찾기 (투 포인터): ([Python 3.7 코드](/20/3.py) / [C++ 코드](/20/3.cpp) / [Java 코드](/20/3.java)) * 정렬되어 있는 두 리스트 합치기 (투 포인터): [Python 3.7 코드](/20/4.py) - * 구간 합: [Python 3.7 코드](/20/5.py) + * 구간 합: ([Python 3.7 코드](/20/5.py) / [C++ 코드](/20/5.cpp) / [Java 코드](/20/5.java)) * 순열: [Python 3.7 코드](/20/6.py) * 조합: [Python 3.7 코드](/20/7.py) * 실전 From 7fb0e9bb34b7f74452a4bb08f960339d1b673429 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 6 Oct 2020 15:53:58 +0900 Subject: [PATCH 17/68] Update notice.md --- notice.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/notice.md b/notice.md index c614182..e2620a5 100644 --- a/notice.md +++ b/notice.md @@ -71,3 +71,9 @@ #### (570p) 예시 설명 * 문제 해설의 예시 설명에 오류가 있습니다. 올바른 설명은 [수정 사항이 반영된 설명 링크](https://github.com/ndb796/python-for-coding-test/blob/master/16/5_notice.md)와 같습니다. + +### 초판 3쇄 + +#### (398p) 문제 내용 + +* 문제 설명에서 두 행성 A와 B를 터널로 연결할 때 드는 비용으로는 min(|xA-xB|, |yA-yB|, |zA-zB|)가 올바른 내용입니다. From 58faaf835f6f1ac763ba2ce4d7a06eb3538ce57a Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 20:57:13 +0900 Subject: [PATCH 18/68] Update 3.java --- 15/3.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/15/3.java b/15/3.java index e69de29..fa481de 100644 --- a/15/3.java +++ b/15/3.java @@ -0,0 +1,48 @@ +import java.util.*; + +public class Main { + + public static void main(String[] args) { + // 집의 개수(N)와 공유기의 개수(C)를 입력받기 + Scanner sc = new Scanner(System.in); + int n = sc.nextInt(); + int c = sc.nextInt(); + + // 전체 집의 좌표 정보를 입력받기 + ArrayList arr = new ArrayList<>(); + for (int i = 0; i < n; i++) { + arr.add(sc.nextInt()); + } + + // 이진 탐색을 위해 정렬 수행 + Collections.sort(arr); + + int start = arr.get(1) - arr.get(0); // 집의 좌표 중에 가장 작은 값 + int end = arr.get(n - 1) - arr.get(0); // 집의 좌표 중에 가장 큰 값 + int result = 0; + + while (start <= end) { + // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + int mid = (start + end) / 2; + int value = arr.get(0); + int cnt = 1; + // 현재의 mid 값을 이용해 공유기를 설치하기 + for (int i = 1; i < n; i++) { // 앞에서부터 차근차근 설치 + if (arr.get(i) >= value + mid) { + value = arr.get(i); + cnt += 1; + } + } + // C개 이상의 공유기를 설치할 수 있는 경우, 거리를 증가시키기 + if (cnt >= c) { + start = mid + 1; + result = mid; // 최적의 결과를 저장 + } + // C개 이상의 공유기를 설치할 수 없는 경우, 거리를 감소시키기 + else { + end = mid - 1; + } + } + System.out.println(result); + } +} From 9cd406803e571cd758985a7589926aef8e4129b9 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 21:00:28 +0900 Subject: [PATCH 19/68] Update 3.java --- 15/3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/15/3.java b/15/3.java index fa481de..b50e99d 100644 --- a/15/3.java +++ b/15/3.java @@ -24,6 +24,7 @@ public static void main(String[] args) { while (start <= end) { // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 int mid = (start + end) / 2; + // 첫째 집에는 무조건 공유기를 설치한다고 가정 int value = arr.get(0); int cnt = 1; // 현재의 mid 값을 이용해 공유기를 설치하기 From f490799dbdae78c6d50a7d62ff0c9259cac2ca2d Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 21:01:42 +0900 Subject: [PATCH 20/68] Update 3.cpp --- 15/3.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/15/3.cpp b/15/3.cpp index dc7226f..abf7922 100644 --- a/15/3.cpp +++ b/15/3.cpp @@ -25,6 +25,7 @@ int main() { while (start <= end) { // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 int mid = (start + end) / 2; + // 첫째 집에는 무조건 공유기를 설치한다고 가정 int value = arr[0]; int cnt = 1; // 현재의 mid 값을 이용해 공유기를 설치하기 @@ -46,4 +47,4 @@ int main() { } cout << result << '\n'; -} \ No newline at end of file +} From 422f11e85c124f22982ff6c6cb39d595d311fb5d Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 21:02:13 +0900 Subject: [PATCH 21/68] Update 3.py --- 15/3.py | 1 + 1 file changed, 1 insertion(+) diff --git a/15/3.py b/15/3.py index b276bbb..2bb1ea6 100644 --- a/15/3.py +++ b/15/3.py @@ -13,6 +13,7 @@ while(start <= end): mid = (start + end) // 2 # mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + # 첫째 집에는 무조건 공유기를 설치한다고 가정 value = array[0] count = 1 # 현재의 mid 값을 이용해 공유기를 설치하기 From 8f369ec82a1b64414d7fe6e437f72afab1f7a920 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 21:21:30 +0900 Subject: [PATCH 22/68] Update 2.java --- 15/2.java | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/15/2.java b/15/2.java index e69de29..f0058e9 100644 --- a/15/2.java +++ b/15/2.java @@ -0,0 +1,32 @@ +import java.util.*; + +public class Main { + + // 이진 탐색 소스코드 구현(재귀 함수) + public static int binarySearch(int[] arr, int start, int end) { + if (start > end) return -1; + int mid = (start + end) / 2; + // 고정점을 찾은 경우 중간점 인덱스 반환 + if (arr[mid] == mid) return mid; + // 중간점의 값보다 중간점이 작은 경우 왼쪽 확인 + else if (arr[mid] > mid) return binarySearch(arr, start, mid - 1); + // 중간점의 값보다 중간점이 큰 경우 오른쪽 확인 + else return binarySearch(arr, mid + 1, end); + } + + 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(); + } + + // 이진 탐색(Binary Search) 수행 + int index = binarySearch(arr, 0, n - 1); + + // 결과 출력 + System.out.println(index); + } +} From 58a0ead96f35c855990dd1bcb83ba17585463a15 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 21:46:17 +0900 Subject: [PATCH 23/68] Update 1.java --- 15/1.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/15/1.java b/15/1.java index e69de29..eb6e7a2 100644 --- a/15/1.java +++ b/15/1.java @@ -0,0 +1,52 @@ +import java.util.*; + +public class Main { + + public static int lowerBound(int[] arr, int target, int start, int end) { + while (start < end) { + int mid = (start + end) / 2; + if (arr[mid] >= target) end = mid; + else start = mid + 1; + } + return end; + } + + public static int upperBound(int[] arr, int target, int start, int end) { + while (start < end) { + int mid = (start + end) / 2; + if (arr[mid] > target) end = mid; + else start = mid + 1; + } + return end; + } + + // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 + public static int countByRange(int[] arr, int leftValue, int rightValue) { + // 유의: lowerBound와 upperBound는 배열의 길이를 end 변수의 값으로 설정 + int rightIndex = upperBound(arr, rightValue, 0, arr.length); + int leftIndex = lowerBound(arr, leftValue, 0, arr.length); + return rightIndex - leftIndex; + } + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + + // 데이터의 개수 N, 찾고자 하는 값 x 입력받기 + int n = sc.nextInt(); + int x = sc.nextInt(); + + // 전체 데이터 입력받기 + int[] arr = new int[n]; + for (int i = 0; i < n; i++) { + arr[i] = sc.nextInt(); + } + + // 값이 [x, x] 범위에 있는 데이터의 개수 계산 + int cnt = countByRange(arr, x, x); + + // 값이 x인 원소가 존재하지 않는다면 + if (cnt == 0) System.out.println(-1); + // 값이 x인 원소가 존재한다면 + else System.out.println(cnt); + } +} From 8d7fd69d822be6f2281d0d92675d08b9502d0d11 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 22:09:09 +0900 Subject: [PATCH 24/68] Update 1.java --- 15/1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/1.java b/15/1.java index eb6e7a2..896f2a6 100644 --- a/15/1.java +++ b/15/1.java @@ -22,7 +22,7 @@ public static int upperBound(int[] arr, int target, int start, int end) { // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 public static int countByRange(int[] arr, int leftValue, int rightValue) { - // 유의: lowerBound와 upperBound는 배열의 길이를 end 변수의 값으로 설정 + // 유의: lowerBound와 upperBound는 end 변수의 값을 배열의 길이로 설정 int rightIndex = upperBound(arr, rightValue, 0, arr.length); int leftIndex = lowerBound(arr, leftValue, 0, arr.length); return rightIndex - leftIndex; From c296da1d0f280c316fdab6062987c111364ac37b Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 22:10:34 +0900 Subject: [PATCH 25/68] Update 4.java --- 15/4.java | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/15/4.java b/15/4.java index e69de29..e751ce6 100644 --- a/15/4.java +++ b/15/4.java @@ -0,0 +1,83 @@ +import java.util.*; + +class Solution { + + public int lowerBound(ArrayList arr, String target, int start, int end) { + while (start < end) { + int mid = (start + end) / 2; + // arr[mid]가 target보다 사전순으로 같거나 뒤에 있다면 + if (arr.get(mid).compareTo(target) >= 0) end = mid; + else start = mid + 1; + } + return end; + } + + public int upperBound(ArrayList arr, String target, int start, int end) { + while (start < end) { + int mid = (start + end) / 2; + // arr[mid]가 target보다 사전순으로 뒤에 있다면 + if (arr.get(mid).compareTo(target) > 0) end = mid; + else start = mid + 1; + } + return end; + } + + // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 + public int countByRange(ArrayList arr, String leftValue, String rightValue) { + // 유의: lowerBound와 upperBound는 end 변수의 값을 배열의 길이로 설정 + int rightIndex = upperBound(arr, rightValue, 0, arr.size()); + int leftIndex = lowerBound(arr, leftValue, 0, arr.size()); + return rightIndex - leftIndex; + } + + // 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트 + ArrayList> arr = new ArrayList>(); + // 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트 + ArrayList> reversedArr = new ArrayList>(); + + public int[] solution(String[] words, String[] queries) { + ArrayList ans = new ArrayList(); + + // 단어의 길이는 10,000까지 가능 + for (int i = 0; i < 10001; i++) { + arr.add(new ArrayList()); + reversedArr.add(new ArrayList()); + } + + // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입 + for (int i = 0; i < words.length; i++) { + String word = words[i]; + arr.get(word.length()).add(word); // 단어를 삽입 + word = (new StringBuffer(word)).reverse().toString(); + reversedArr.get(word.length()).add(word); // 단어를 뒤집어서 삽입 + } + + // 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행 + for (int i = 0; i < 10001; i++) { + Collections.sort(arr.get(i)); + Collections.sort(reversedArr.get(i)); + } + + // 쿼리를 하나씩 확인하며 처리 + for (int i = 0; i < queries.length; i++) { + String q = queries[i]; + int res = 0; + if (q.charAt(0) != '?') { // 접미사에 와일드 카드가 붙은 경우 + res = countByRange(arr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z")); + } + else { // 접두사에 와일드 카드가 붙은 경우 + q = (new StringBuffer(q)).reverse().toString(); + res = countByRange(reversedArr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z")); + } + // 검색된 단어의 개수를 저장 + ans.add(res); + } + + // 배열로 바꾸어 반환 + int[] answer = new int[ans.size()]; + for (int i = 0; i < ans.size(); i++) { + answer[i] = ans.get(i); + } + return answer; + } +} From 4c55c1737fa483739a1a612ba5f5c6ffc36bec98 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 22:12:56 +0900 Subject: [PATCH 26/68] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 51e3822..e109865 100644 --- a/README.md +++ b/README.md @@ -197,10 +197,10 @@ #### 15장 이진 탐색 -* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): ([Python 3.7 코드](/15/1.py) / [C++ 코드](/15/1.cpp)) -* 고정점 찾기 (Amazon 인터뷰 기출): ([Python 3.7 코드](/15/2.py) / [C++ 코드](/15/2.cpp)) -* [공유기 설치](https://www.acmicpc.net/problem/2110) (핵심 유형): ([Python 3.7 코드](/15/3.py) / [C++ 코드](/15/3.cpp)) -* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): ([Python 3.7 코드](/15/4.py) / [C++ 코드](/15/4.cpp)) +* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): ([Python 3.7 코드](/15/1.py) / [C++ 코드](/15/1.cpp) / [Java 코드](/15/1.java)) +* 고정점 찾기 (Amazon 인터뷰 기출): ([Python 3.7 코드](/15/2.py) / [C++ 코드](/15/2.cpp) / [Java 코드](/15/2.java)) +* [공유기 설치](https://www.acmicpc.net/problem/2110) (핵심 유형): ([Python 3.7 코드](/15/3.py) / [C++ 코드](/15/3.cpp) / [Java 코드](/15/3.java)) +* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): ([Python 3.7 코드](/15/4.py) / [C++ 코드](/15/4.cpp) / [Java 코드](/15/4.java)) #### 16장 다이나믹 프로그래밍 From fd705d25b7c3d94e5813dbe4047371bdf8967438 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 22:21:43 +0900 Subject: [PATCH 27/68] Update 4.java --- 15/4.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/15/4.java b/15/4.java index e751ce6..09e91c7 100644 --- a/15/4.java +++ b/15/4.java @@ -31,9 +31,9 @@ public int countByRange(ArrayList arr, String leftValue, String rightVal } // 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트 - ArrayList> arr = new ArrayList>(); + public ArrayList> arr = new ArrayList>(); // 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트 - ArrayList> reversedArr = new ArrayList>(); + public ArrayList> reversedArr = new ArrayList>(); public int[] solution(String[] words, String[] queries) { ArrayList ans = new ArrayList(); From 94cb80b6cc7cba1cb4af7e845d9f965fc6cf0fda Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 23:08:57 +0900 Subject: [PATCH 28/68] Update 6.java --- 12/6.java | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/12/6.java b/12/6.java index e69de29..28c4347 100644 --- a/12/6.java +++ b/12/6.java @@ -0,0 +1,143 @@ +import java.util.*; + +class Node implements Comparable { + + private int x; + private int y; + private int stuff; + + public Node(int x, int y, int stuff) { + this.x = x; + this.y = y; + this.stuff = stuff; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getStuff() { + return this.stuff; + } + + // 정렬 기준 설정 (x, y, stuff 순서대로 오름차순) + @Override + public int compareTo(Node other) { + if (this.x == other.x && this.y == other.y) { + return Integer.compare(this.stuff, other.stuff); + } + if (this.x == other.x) { + return Integer.compare(this.y, other.y); + } + return Integer.compare(this.x, other.x); + } +} + +class Solution { + + // 현재 설치된 구조물이 '가능한' 구조물인지 확인하는 함수 + public boolean possible(ArrayList> answer) { + for (int i = 0; i < answer.size(); i++) { + int x = answer.get(i).get(0); + int y = answer.get(i).get(1); + int stuff = answer.get(i).get(2); + if (stuff == 0) { // 설치된 것이 '기둥'인 경우 + boolean check = false; + // '바닥 위'라면 정상 + if (y == 0) check = true; + // '보의 한 쪽 끝 부분 위' 혹은 '다른 기둥 위'라면 정상 + for (int j = 0; j < answer.size(); j++) { + if (x - 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) { + check = true; + } + if (x == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) { + check = true; + } + if (x == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) { + check = true; + } + } + if (!check) return false; // 아니라면 거짓(False) 반환 + } + else if (stuff == 1) { // 설치된 것이 '보'인 경우 + boolean check = false; + boolean left = false; + boolean right = false; + // '한쪽 끝부분이 기둥 위' 혹은 '양쪽 끝부분이 다른 보와 동시에 연결'이라면 정상 + for (int j = 0; j < answer.size(); j++) { + if (x == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) { + check = true; + } + if (x + 1 == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) { + check = true; + } + if (x - 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) { + left = true; + } + if (x + 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) { + right = true; + } + } + if (left && right) check = true; + if (!check) return false; // 아니라면 거짓(False) 반환 + } + } + return true; + } + + public int[][] solution(int n, int[][] build_frame) { + ArrayList> answer = new ArrayList>(); + // 작업(frame)의 개수는 최대 1,000개 + for (int i = 0; i < build_frame.length; i++) { + int x = build_frame[i][0]; + int y = build_frame[i][1]; + int stuff = build_frame[i][2]; + int operate = build_frame[i][3]; + if (operate == 0) { // 삭제하는 경우 + // 일단 삭제를 해 본 뒤에 + int index = 0; + for (int j = 0; j < answer.size(); j++) { + if (x == answer.get(j).get(0) && y == answer.get(j).get(1) && stuff == answer.get(j).get(2)) { + index = j; + } + } + ArrayList erased = answer.get(index); + answer.remove(index); + if (!possible(answer)) { // 가능한 구조물인지 확인 + answer.add(erased); // 가능한 구조물이 아니라면 다시 설치 + } + } + if (operate == 1) { // 설치하는 경우 + // 일단 설치를 해 본 뒤에 + ArrayList inserted = new ArrayList(); + inserted.add(x); + inserted.add(y); + inserted.add(stuff); + answer.add(inserted); + if (!possible(answer)) { // 가능한 구조물인지 확인 + answer.remove(answer.size() - 1); // 가능한 구조물이 아니라면 다시 제거 + } + } + } + + // 정렬 수행 + ArrayList ans = new ArrayList(); + for (int i = 0; i < answer.size(); i++) { + ans.add(new Node(answer.get(i).get(0), answer.get(i).get(1), answer.get(i).get(2))); + } + Collections.sort(ans); + + // 배열로 바꾸어 반환 + int[][] res = new int[ans.size()][3]; + for (int i = 0; i < ans.size(); i++) { + res[i][0] = ans.get(i).getX(); + res[i][1] = ans.get(i).getY(); + res[i][2] = ans.get(i).getStuff(); + } + return res; + } +} From 77fa1e4bcdf33edde0047087eea5c7155dd0e748 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 23:10:30 +0900 Subject: [PATCH 29/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e109865..429823b 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ * [문자열 압축](https://programmers.co.kr/learn/courses/30/lessons/60057) (카카오): ([Python 3.7 코드](/12/3.py) / [C++ 코드](/12/3.cpp) / [Java 코드](/12/3.java)) * [자물쇠와 열쇠](https://programmers.co.kr/learn/courses/30/lessons/60059) (카카오): ([Python 3.7 코드](/12/4.py) / [C++ 코드](/12/4.cpp) / [Java 코드](/12/4.java)) * [뱀](https://www.acmicpc.net/problem/3190) (삼성): ([Python 3.7 코드](/12/5.py) / [C++ 코드](/12/5.cpp) / [Java 코드](/12/5.java)) -* [기둥과 보 설치](https://programmers.co.kr/learn/courses/30/lessons/60061) (카카오): ([Python 3.7 코드](/12/6.py) / [C++ 코드](/12/6.cpp)) +* [기둥과 보 설치](https://programmers.co.kr/learn/courses/30/lessons/60061) (카카오): ([Python 3.7 코드](/12/6.py) / [C++ 코드](/12/6.cpp) / [Java 코드](/12/6.java)) * [치킨 배달](https://www.acmicpc.net/problem/15686) (삼성): ([Python 3.7 코드](/12/7.py) / [C++ 코드](/12/7.cpp) / [Java 코드](/12/7.java)) * [외벽 점검](https://programmers.co.kr/learn/courses/30/lessons/60062) (카카오): ([Python 3.7 코드](/12/8.py) / [C++ 코드](/12/8.cpp) / [Java 코드](/12/8.java)) From eaaf71f61a98f0ff4c90ebc74a2322e70e3ad3fb Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 23:39:26 +0900 Subject: [PATCH 30/68] Update 4.java --- 13/4.java | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/13/4.java b/13/4.java index e69de29..9e1e854 100644 --- a/13/4.java +++ b/13/4.java @@ -0,0 +1,56 @@ +import java.util.*; + +class Solution { + + // "균형잡힌 괄호 문자열"의 인덱스 반환 + public int balancedIndex(String p) { + int count = 0; // 왼쪽 괄호의 개수 + for (int i = 0; i < p.length(); i++) { + if (p.charAt(i) == '(') count += 1; + else count -= 1; + if (count == 0) return i; + } + return -1; + } + + // "올바른 괄호 문자열"인지 판단 + public boolean checkProper(String p) { + int count = 0; // 왼쪽 괄호의 개수 + for (int i = 0; i < p.length(); i++) { + if (p.charAt(i) == '(') count += 1; + else { + if (count == 0) { // 쌍이 맞지 않는 경우에 false 반환 + return false; + } + count -= 1; + } + } + return true; // 쌍이 맞는 경우에 true 반환 + } + + public String solution(String p) { + String answer = ""; + if (p.equals("")) return answer; + int index = balancedIndex(p); + String u = p.substring(0, index + 1); + String v = p.substring(index + 1); + // "올바른 괄호 문자열"이면, v에 대해 함수를 수행한 결과를 붙여 반환 + if (checkProper(u)) { + answer = u + solution(v); + } + // "올바른 괄호 문자열"이 아니라면 아래의 과정을 수행 + else { + answer = "("; + answer += solution(v); + answer += ")"; + u = u.substring(1, u.length() - 1); // 첫 번째와 마지막 문자를 제거 + String temp = ""; + for (int i = 0; i < u.length(); i++) { + if (u.charAt(i) == '(') temp += ")"; + else temp += "("; + } + answer += temp; + } + return answer; + } +} From 8b766c7061f8c9f14d9305133f8fadcf14c0ed06 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 23:40:10 +0900 Subject: [PATCH 31/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 429823b..9f6640a 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ * [특정 거리의 도시 찾기](https://www.acmicpc.net/problem/18352) (핵심 유형): ([Python 3.7 코드](/13/1.py) / [C++ 코드](/13/1.cpp) / [Java 코드](/13/1.java)) * [연구소](https://www.acmicpc.net/problem/14502) (삼성): ([Python 3.7 코드](/13/2.py) / [C++ 코드](/13/2.cpp) / [Java 코드](/13/2.java)) * [경쟁적 전염](https://www.acmicpc.net/problem/18405) (핵심 유형): ([Python 3.7 코드](/13/3.py) / [C++ 코드](/13/3.cpp) / [Java 코드](/13/3.java)) -* [괄호 변환](https://programmers.co.kr/learn/courses/30/lessons/60058) (카카오): ([Python 3.7 코드](/13/4.py) / [C++ 코드](/13/4.cpp)) +* [괄호 변환](https://programmers.co.kr/learn/courses/30/lessons/60058) (카카오): ([Python 3.7 코드](/13/4.py) / [C++ 코드](/13/4.cpp) / [Java 코드](/13/4.java)) * [연산자 끼워 넣기](https://www.acmicpc.net/problem/14888) (삼성): ([Python 3.7 코드](/13/5.py) / [C++ 코드](/13/5.cpp) / [Java 코드](/13/5.java)) * [감시 피하기](https://www.acmicpc.net/problem/18428) (핵심 유형): ([Python 3.7 코드](/13/6.py) / [C++ 코드](/13/6.cpp) / [Java 코드](/13/6.java)) * [인구 이동](https://www.acmicpc.net/problem/16234) (삼성): ([Python 3.7 코드](/13/7.py) / [C++ 코드](/13/7.cpp) / [Java 코드](/13/7.java)) From cb4676efe896142b731834b20081dd31534f730f Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Fri, 9 Oct 2020 23:57:05 +0900 Subject: [PATCH 32/68] Update 8.cpp --- 13/8.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13/8.cpp b/13/8.cpp index caffba7..3910883 100644 --- a/13/8.cpp +++ b/13/8.cpp @@ -42,7 +42,7 @@ vector getNextPos(Node pos, vector > board) { } } } - // 현재 로봇이 가로로 놓여 있는 경우 + // 현재 로봇이 세로로 놓여 있는 경우 int ver[] = {-1, 1}; if (pos.pos1Y == pos.pos2Y) { for (int i = 0; i < 2; i++) { // 왼쪽으로 회전하거나, 오른쪽으로 회전 From d39d68bfd1bc017369793a48cfa432afaaa7c41b Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 10 Oct 2020 00:14:22 +0900 Subject: [PATCH 33/68] Update 8.java --- 13/8.java | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/13/8.java b/13/8.java index e69de29..4329e56 100644 --- a/13/8.java +++ b/13/8.java @@ -0,0 +1,127 @@ +import java.util.*; + +class Node { + private int pos1X; + private int pos1Y; + private int pos2X; + private int pos2Y; + private int distance; + + public int getPos1X() { + return this.pos1X; + } + public int getPos1Y() { + return this.pos1Y; + } + public int getPos2X() { + return this.pos2X; + } + public int getPos2Y() { + return this.pos2Y; + } + public int getDistance() { + return this.distance; + } + + public Node(int pos1X, int pos1Y, int pos2X, int pos2Y, int distance) { + this.pos1X = pos1X; + this.pos1Y = pos1Y; + this.pos2X = pos2X; + this.pos2Y = pos2Y; + this.distance = distance; + } +} + +class Solution { + + public ArrayList getNextPos(Node pos, int[][] board) { + // 반환 결과(이동 가능한 위치들) + ArrayList nextPos = new ArrayList(); + // (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리 + int[] dx = {-1, 1, 0, 0}; + int[] dy = {0, 0, -1, 1}; + for (int i = 0; i < 4; i++) { + int pos1NextX = pos.getPos1X() + dx[i]; + int pos1NextY = pos.getPos1Y() + dy[i]; + int pos2NextX = pos.getPos2X() + dx[i]; + int pos2NextY = pos.getPos2Y() + dy[i]; + int distanceNext = pos.getDistance() + 1; + // 이동하고자 하는 두 칸이 모두 비어 있다면 + if (board[pos1NextX][pos1NextY] == 0 && board[pos2NextX][pos2NextY] == 0) { + nextPos.add(new Node(pos1NextX, pos1NextY, pos2NextX, pos2NextY, distanceNext)); + } + } + // 현재 로봇이 가로로 놓여 있는 경우 + int[] hor = {-1, 1}; + if (pos.getPos1X() == pos.getPos2X()) { + for (int i = 0; i < 2; i++) { // 위쪽으로 회전하거나, 아래쪽으로 회전 + // 위쪽 혹은 아래쪽 두 칸이 모두 비어 있다면 + if (board[pos.getPos1X() + hor[i]][pos.getPos1Y()] == 0 && board[pos.getPos2X() + hor[i]][pos.getPos2Y()] == 0) { + nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X() + hor[i], pos.getPos1Y(), pos.getDistance() + 1)); + nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X() + hor[i], pos.getPos2Y(), pos.getDistance() + 1)); + } + } + } + // 현재 로봇이 세로로 놓여 있는 경우 + int[] ver = {-1, 1}; + if (pos.getPos1Y() == pos.getPos2Y()) { + for (int i = 0; i < 2; i++) { // 왼쪽으로 회전하거나, 오른쪽으로 회전 + // 왼쪽 혹은 오른쪽 두 칸이 모두 비어 있다면 + if (board[pos.getPos1X()][pos.getPos1Y() + ver[i]] == 0 && board[pos.getPos2X()][pos.getPos2Y() + ver[i]] == 0) { + nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X(), pos.getPos1Y() + ver[i], pos.getDistance() + 1)); + nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X(), pos.getPos2Y() + ver[i], pos.getDistance() + 1)); + } + } + } + // 현재 위치에서 이동할 수 있는 위치를 반환 + return nextPos; + } + + public int solution(int[][] board) { + // 맵 외곽에 벽을 두는 형태로 맵 변형 + int n = board.length; + int[][] newBoard = new int[n + 2][n + 2]; + for (int i = 0; i < n + 2; i++) { + for (int j = 0; j < n + 2; j++) { + newBoard[i][j] = 1; + } + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + newBoard[i + 1][j + 1] = board[i][j]; + } + } + // 너비 우선 탐색(BFS) 수행 + Queue q = new LinkedList<>(); + ArrayList visited = new ArrayList<>(); + Node pos = new Node(1, 1, 1, 2, 0); // 시작 위치 설정 + q.offer(pos); // 큐에 삽입한 뒤에 + visited.add(pos); // 방문 처리 + // 큐가 빌 때까지 반복 + while (!q.isEmpty()) { + pos = q.poll(); + // (n, n) 위치에 로봇이 도달했다면, 최단 거리이므로 반환 + if ((pos.getPos1X() == n && pos.getPos1Y() == n) || (pos.getPos2X() == n && pos.getPos2Y() == n)) { + return pos.getDistance(); + } + // 현재 위치에서 이동할 수 있는 위치 확인 + ArrayList nextPos = getNextPos(pos, newBoard); + for (int i = 0; i < nextPos.size(); i++) { + // 아직 방문하지 않은 위치라면 큐에 삽입하고 방문 처리 + boolean check = true; + pos = nextPos.get(i); + for (int j = 0; j < visited.size(); j++) { + if (pos.getPos1X() == visited.get(j).getPos1X() && pos.getPos1Y() == visited.get(j).getPos1Y() && pos.getPos2X() == visited.get(j).getPos2X() && pos.getPos2Y() == visited.get(j).getPos2Y()) { + check = false; + break; + } + } + if (check) { + q.offer(pos); + visited.add(pos); + } + } + } + return 0; + } +} From c362b40260347899a9237b102e95a5a90f1fe7d7 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 10 Oct 2020 00:15:20 +0900 Subject: [PATCH 34/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f6640a..7653e26 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ * [연산자 끼워 넣기](https://www.acmicpc.net/problem/14888) (삼성): ([Python 3.7 코드](/13/5.py) / [C++ 코드](/13/5.cpp) / [Java 코드](/13/5.java)) * [감시 피하기](https://www.acmicpc.net/problem/18428) (핵심 유형): ([Python 3.7 코드](/13/6.py) / [C++ 코드](/13/6.cpp) / [Java 코드](/13/6.java)) * [인구 이동](https://www.acmicpc.net/problem/16234) (삼성): ([Python 3.7 코드](/13/7.py) / [C++ 코드](/13/7.cpp) / [Java 코드](/13/7.java)) -* [블록 이동하기](https://programmers.co.kr/learn/courses/30/lessons/60063) (카카오): ([Python 3.7 코드](/13/8.py) / [C++ 코드](/13/8.cpp)) +* [블록 이동하기](https://programmers.co.kr/learn/courses/30/lessons/60063) (카카오): ([Python 3.7 코드](/13/8.py) / [C++ 코드](/13/8.cpp) / [Java 코드](/13/8.java)) #### 14장 정렬 From afab1d06ec05d439b66c433db83543861f8db30d Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 24 Oct 2020 16:27:37 +0900 Subject: [PATCH 35/68] Update notice.md --- notice.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notice.md b/notice.md index e2620a5..0ce385a 100644 --- a/notice.md +++ b/notice.md @@ -37,6 +37,10 @@ * N과 M의 입력 범위는 (1 ≤ N, M ≤ 100,000)입니다. +#### (368p) '고정점 찾기' 문제 설명 누락 + +* 고정점은 최대 1개만 존재합니다. + #### (423p) 두 번째 예제와 세 번째 예제 실행 결과 오류 * 두 번째 예제와 세 번째 예제의 실행 결과가 잘못 기재되어 있습니다. 올바른 실행 결과는 다음과 같습니다. From 845ec3d9a896b8e23820535c81050db7712d5458 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Sat, 24 Oct 2020 16:31:16 +0900 Subject: [PATCH 36/68] Update notice.md --- notice.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/notice.md b/notice.md index 0ce385a..0440783 100644 --- a/notice.md +++ b/notice.md @@ -78,6 +78,10 @@ ### 초판 3쇄 -#### (398p) 문제 내용 +#### (375p) '금광' 문제의 입력 조건 오류 + +* 각 위치에 매장된 금의 개수는 1 이상이 아닌 0 이상입니다. + +#### (398p) 문제 내용 오탈자 * 문제 설명에서 두 행성 A와 B를 터널로 연결할 때 드는 비용으로는 min(|xA-xB|, |yA-yB|, |zA-zB|)가 올바른 내용입니다. From 2237a16f3491a704a7207a99ffebd4bf34da5f6f Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:08:09 +0900 Subject: [PATCH 37/68] Update README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 7653e26..4494d16 100644 --- a/README.md +++ b/README.md @@ -318,3 +318,14 @@ * 회원 정보 처리 실습 #### 부록 D 알고리즘 유형별 문제 풀이 + +### 추가 자료 + +* 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다. + +1. 트리(Tree) +2. 우선순위 큐(Priority Queue) + * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/1.py) / [C++ 코드](/21/1.cpp)) +3. 인덱스 트리(Indexed Tree) +4. 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 +5. 최소 공통 조상(Lowest Common Ancestor, LCA) From 9b9ec1460e4d14191cb1cdb4161213fcd185e000 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:08:38 +0900 Subject: [PATCH 38/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4494d16..0e3200c 100644 --- a/README.md +++ b/README.md @@ -325,7 +325,7 @@ 1. 트리(Tree) 2. 우선순위 큐(Priority Queue) - * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/1.py) / [C++ 코드](/21/1.cpp)) + * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/1.py) / [C++ 코드](/21/1.cpp)) 3. 인덱스 트리(Indexed Tree) 4. 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 5. 최소 공통 조상(Lowest Common Ancestor, LCA) From 6baeec0f0ff9180f5cd7e246427e795ed4822171 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:09:07 +0900 Subject: [PATCH 39/68] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0e3200c..4a811e0 100644 --- a/README.md +++ b/README.md @@ -321,11 +321,11 @@ ### 추가 자료 -* 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다. +> 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다. -1. 트리(Tree) -2. 우선순위 큐(Priority Queue) +* 트리(Tree) +* 우선순위 큐(Priority Queue) * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/1.py) / [C++ 코드](/21/1.cpp)) -3. 인덱스 트리(Indexed Tree) -4. 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 -5. 최소 공통 조상(Lowest Common Ancestor, LCA) +* 인덱스 트리(Indexed Tree) +* 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 +* 최소 공통 조상(Lowest Common Ancestor, LCA) From 1a22b412e9a24ca2dce30183f7fad3ef478ab77c Mon Sep 17 00:00:00 2001 From: ndb796 Date: Mon, 2 Nov 2020 14:12:08 +0900 Subject: [PATCH 40/68] Update --- 21/1.cpp | 0 21/1.py | 0 21/2.cpp | 0 21/2.py | 0 21/3.cpp | 0 21/3.py | 0 21/4.cpp | 0 21/4.py | 0 21/5.cpp | 0 21/5.py | 0 21/6.cpp | 0 21/6.py | 0 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 21/1.cpp create mode 100644 21/1.py create mode 100644 21/2.cpp create mode 100644 21/2.py create mode 100644 21/3.cpp create mode 100644 21/3.py create mode 100644 21/4.cpp create mode 100644 21/4.py create mode 100644 21/5.cpp create mode 100644 21/5.py create mode 100644 21/6.cpp create mode 100644 21/6.py diff --git a/21/1.cpp b/21/1.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/1.py b/21/1.py new file mode 100644 index 0000000..e69de29 diff --git a/21/2.cpp b/21/2.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/2.py b/21/2.py new file mode 100644 index 0000000..e69de29 diff --git a/21/3.cpp b/21/3.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/3.py b/21/3.py new file mode 100644 index 0000000..e69de29 diff --git a/21/4.cpp b/21/4.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/4.py b/21/4.py new file mode 100644 index 0000000..e69de29 diff --git a/21/5.cpp b/21/5.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/5.py b/21/5.py new file mode 100644 index 0000000..e69de29 diff --git a/21/6.cpp b/21/6.cpp new file mode 100644 index 0000000..e69de29 diff --git a/21/6.py b/21/6.py new file mode 100644 index 0000000..e69de29 From 7c159863e53785233ec6f3862a55662e85716ac0 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:16:17 +0900 Subject: [PATCH 41/68] Update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a811e0..2e80ff1 100644 --- a/README.md +++ b/README.md @@ -324,8 +324,13 @@ > 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다. * 트리(Tree) + * 트리의 순회: ([Python 3.7 코드](/21/1.py)) * 우선순위 큐(Priority Queue) - * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/1.py) / [C++ 코드](/21/1.cpp)) -* 인덱스 트리(Indexed Tree) + * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/2.py) / [C++ 코드](/21/2.cpp)) +* 바이너리 인덱스 트리(Binary Indexed Tree, BIT, Fenwick Tree) + * [구간 합 구하기(]https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp)) * 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 + * [음수 간선이 포함된 그래프에서의 최단 경로 찾기]https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp)) * 최소 공통 조상(Lowest Common Ancestor, LCA) + * [LCA 기본](https://www.acmicpc.net/problem/11437): ([Python 3.7 코드](/21/5.py) / [C++ 코드](/21/5.cpp)) + * [LCA 심화](https://www.acmicpc.net/problem/11438): ([Python 3.7 코드](/21/6.py) / [C++ 코드](/21/6.cpp)) From d8d87470873f489b876f3c53a9b933597badb1db Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:16:33 +0900 Subject: [PATCH 42/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e80ff1..e146dea 100644 --- a/README.md +++ b/README.md @@ -330,7 +330,7 @@ * 바이너리 인덱스 트리(Binary Indexed Tree, BIT, Fenwick Tree) * [구간 합 구하기(]https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp)) * 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 - * [음수 간선이 포함된 그래프에서의 최단 경로 찾기]https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp)) + * [음수 간선이 포함된 그래프에서의 최단 경로 찾기](https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp)) * 최소 공통 조상(Lowest Common Ancestor, LCA) * [LCA 기본](https://www.acmicpc.net/problem/11437): ([Python 3.7 코드](/21/5.py) / [C++ 코드](/21/5.cpp)) * [LCA 심화](https://www.acmicpc.net/problem/11438): ([Python 3.7 코드](/21/6.py) / [C++ 코드](/21/6.cpp)) From a9ca1b99b9d41e9e12ae33511f0880ed9a07c37b Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:16:55 +0900 Subject: [PATCH 43/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e146dea..b0d3049 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ * 우선순위 큐(Priority Queue) * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/2.py) / [C++ 코드](/21/2.cpp)) * 바이너리 인덱스 트리(Binary Indexed Tree, BIT, Fenwick Tree) - * [구간 합 구하기(]https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp)) + * [구간 합 구하기](https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp)) * 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 * [음수 간선이 포함된 그래프에서의 최단 경로 찾기](https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp)) * 최소 공통 조상(Lowest Common Ancestor, LCA) From 3c7d00f86e7e1cac81797b8221808dc16af0e882 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:18:55 +0900 Subject: [PATCH 44/68] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0d3049..ef4e966 100644 --- a/README.md +++ b/README.md @@ -319,7 +319,7 @@ #### 부록 D 알고리즘 유형별 문제 풀이 -### 추가 자료 +### 추가 보충 자료 > 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다. From 6c7661b63dff7c01ec49f32ab4b2770351f8f8e8 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:19:22 +0900 Subject: [PATCH 45/68] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef4e966..65a62b3 100644 --- a/README.md +++ b/README.md @@ -325,12 +325,12 @@ * 트리(Tree) * 트리의 순회: ([Python 3.7 코드](/21/1.py)) -* 우선순위 큐(Priority Queue) +* 우선순위 큐 (Priority Queue) * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/2.py) / [C++ 코드](/21/2.cpp)) -* 바이너리 인덱스 트리(Binary Indexed Tree, BIT, Fenwick Tree) +* 바이너리 인덱스 트리 (Binary Indexed Tree, BIT, Fenwick Tree) * [구간 합 구하기](https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp)) -* 벨만-포드(Bellman-Ford) 최단 경로 알고리즘 +* 벨만-포드 (Bellman-Ford) 최단 경로 알고리즘 * [음수 간선이 포함된 그래프에서의 최단 경로 찾기](https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp)) -* 최소 공통 조상(Lowest Common Ancestor, LCA) +* 최소 공통 조상 (Lowest Common Ancestor, LCA) * [LCA 기본](https://www.acmicpc.net/problem/11437): ([Python 3.7 코드](/21/5.py) / [C++ 코드](/21/5.cpp)) * [LCA 심화](https://www.acmicpc.net/problem/11438): ([Python 3.7 코드](/21/6.py) / [C++ 코드](/21/6.cpp)) From 33363aaf36ad2a0f7be735c0a7c96867fcb8c86d Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:29:39 +0900 Subject: [PATCH 46/68] Update 2.py --- 21/2.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/21/2.py b/21/2.py index e69de29..7e95dad 100644 --- a/21/2.py +++ b/21/2.py @@ -0,0 +1,25 @@ +import sys +import heapq +input = sys.stdin.readline + +def heapsort(iterable): + h = [] + result = [] + # 모든 원소를 차례대로 힙에 삽입 + for value in iterable: + heapq.heappush(h, value) + # 힙에 삽입된 모든 원소를 차례대로 꺼내어 담기 + for i in range(len(h)): + result.append(heapq.heappop(h)) + return result + +n = int(input()) +arr = [] + +for i in range(n): + arr.append(int(input())) + +res = heapsort(arr) + +for i in range(n): + print(res[i]) From 1c1e50315b57dfcd7e202118281f7aa58732cbb7 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 14:31:51 +0900 Subject: [PATCH 47/68] Update 2.cpp --- 21/2.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/21/2.cpp b/21/2.cpp index e69de29..b723d60 100644 --- a/21/2.cpp +++ b/21/2.cpp @@ -0,0 +1,29 @@ +#include + +using namespace std; + +void heapSort(vector& arr) { + priority_queue h; + // 모든 원소를 차례대로 힙에 삽입 + for (int i = 0; i < arr.size(); i++) { + h.push(-arr[i]); + } + // 힙에 삽입된 모든 원소를 차례대로 꺼내어 출력 + while (!h.empty()) { + printf("%d\n", -h.top()); + h.pop(); + } +} + +int n; +vector arr; + +int main() { + cin >> n; + for (int i = 0; i < n; i++) { + int x; + scanf("%d", &x); + arr.push_back(x); + } + heapSort(arr); +} From fe622e9c597aa0c7bb5e7378e936bb5191619f2c Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:10:09 +0900 Subject: [PATCH 48/68] Delete 1.cpp --- 21/1.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 21/1.cpp diff --git a/21/1.cpp b/21/1.cpp deleted file mode 100644 index e69de29..0000000 From 1f363a586d3cf598dca349658d60183078c259c2 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:10:49 +0900 Subject: [PATCH 49/68] Update 1.py --- 21/1.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/21/1.py b/21/1.py index e69de29..db6f7b7 100644 --- a/21/1.py +++ b/21/1.py @@ -0,0 +1,63 @@ +class Node: + def __init__(self, data, left_node, right_node): + self.data = data + self.left_node = left_node + self.right_node = right_node + +# 전위 순회(Preorder Traversal) +def pre_order(node): + print(node.data, end=' ') + if node.left_node != None: + pre_order(tree[node.left_node]) + if node.right_node != None: + pre_order(tree[node.right_node]) + +# 중위 순회(Inorder Traversal) +def in_order(node): + if node.left_node != None: + in_order(tree[node.left_node]) + print(node.data, end=' ') + if node.right_node != None: + in_order(tree[node.right_node]) + +# 후위 순회(Postorder Traversal) +def post_order(node): + if node.left_node != None: + post_order(tree[node.left_node]) + if node.right_node != None: + post_order(tree[node.right_node]) + print(node.data, end=' ') + +n = int(input()) +tree = {} + +for i in range(n): + data, left_node, right_node = input().split() + if left_node == "None": + left_node = None + if right_node == "None": + right_node = None + tree[data] = Node(data, left_node, right_node) + +pre_order(tree['A']) +print() +in_order(tree['A']) +print() +post_order(tree['A']) + +''' +[예시 입력] +7 +A B C +B D E +C F G +D None None +E None None +F None None +G None None + +[예시 출력] +A B D E C F G +D B E A F C G +D E B F G C A +''' From 171b28e0c25852008e9437076b215d31544f63ef Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:23:57 +0900 Subject: [PATCH 50/68] Update 5.py --- 21/5.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/21/5.py b/21/5.py index e69de29..28fc400 100644 --- a/21/5.py +++ b/21/5.py @@ -0,0 +1,46 @@ +import sys +sys.setrecursionlimit(int(1e5)) # 런타임 오류를 피하기 위한 재귀 깊이 제한 설정 + +n = int(input()) + +parent = [0] * (n + 1) # 부모 노드 정보 +d = [0] * (n + 1) # 각 노드까지의 깊이 +c = [0] * (n + 1) # 각 노드의 깊이가 계산되었는지 여부 +graph = [[] for _ in range(n + 1)] # 그래프(graph) 정보 + +for _ in range(n - 1): + a, b = map(int, input().split()) + graph[a].append(b) + graph[b].append(a) + +# 루트 노드부터 시작하여 깊이(depth)를 구하는 함수 +def dfs(x, depth): + c[x] = True + d[x] = depth + for y in graph[x]: + if c[y]: # 이미 깊이를 구했다면 넘기기 + continue + parent[y] = x + dfs(y, depth + 1) + +# A와 B의 최소 공통 조상을 찾는 함수 +def lca(a, b): + # 먼저 깊이(depth)가 동일하도록 + while d[a] != d[b]: + if d[a] > d[b]: + a = parent[a] + else: + b = parent[b] + # 노드가 같아지도록 + while a != b: + a = parent[a] + b = parent[b] + return a + +dfs(1, 0) # 루트 노드는 1번 노드 + +m = int(input()) + +for i in range(m): + a, b = map(int, input().split()) + print(lca(a, b)) From d6b235f52d131919011b3cc7edc15f86ec60f1c4 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:25:33 +0900 Subject: [PATCH 51/68] Update 5.cpp --- 21/5.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/21/5.cpp b/21/5.cpp index e69de29..a1ab904 100644 --- a/21/5.cpp +++ b/21/5.cpp @@ -0,0 +1,57 @@ +#include +#define MAX 100001 + +using namespace std; + +int n, m; +int parent[MAX]; // 부모에 대한 정보 +int d[MAX]; // 각 노드까지의 깊이(depth) +int c[MAX]; // 각 노드의 깊이가 계산되었는지 여부 +vector graph[MAX]; // 그래프(graph) 정보 + +// 루트 노드부터 시작하여 깊이(depth)를 구하는 함수 +void dfs(int x, int depth) { + c[x] = true; + d[x] = depth; + for (int i = 0; i < graph[x].size(); i++) { + int y = graph[x][i]; + if (c[y]) continue; // 이미 깊이를 구했다면 넘기기 + parent[y] = x; + dfs(y, depth + 1); + } +} + +// A와 B의 최소 공통 조상을 찾는 함수 +int lca(int a, int b) { + // 먼저 깊이(depth)가 동일하도록 + while (d[a] != d[b]) { + if (d[a] > d[b]) { + a = parent[a]; + } + else b = parent[b]; + } + // 노드가 같아지도록 + while (a != b) { + a = parent[a]; + b = parent[b]; + } + return a; +} + +int main() { + cin >> n; + for (int i = 0; i < n - 1; i++) { + int a, b; + cin >> a >> b; + graph[a].push_back(b); + graph[b].push_back(a); + } + dfs(1, 0); // 루트 노드는 1번 노드 + + cin >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + cout << lca(a, b) << '\n'; + } +} From 4324395e614ac5018c50dd37219b6411378959b2 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:28:48 +0900 Subject: [PATCH 52/68] Update 6.py --- 21/6.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/21/6.py b/21/6.py index e69de29..2c80e57 100644 --- a/21/6.py +++ b/21/6.py @@ -0,0 +1,60 @@ +import sys +input = sys.stdin.readline # 시간 초과를 피하기 위한 빠른 입력 함수 +sys.setrecursionlimit(int(1e5)) # 런타임 오류를 피하기 위한 재귀 깊이 제한 설정 +LOG = 21 # 2^20 = 1,000,000 + +n = int(input()) +parent = [[0] * LOG for _ in range(n + 1)] # 부모 노드 정보 +d = [0] * (n + 1) # 각 노드까지의 깊이 +c = [0] * (n + 1) # 각 노드의 깊이가 계산되었는지 여부 +graph = [[] for _ in range(n + 1)] # 그래프(graph) 정보 + +for _ in range(n - 1): + a, b = map(int, input().split()) + graph[a].append(b) + graph[b].append(a) + +# 루트 노드부터 시작하여 깊이(depth)를 구하는 함수 +def dfs(x, depth): + c[x] = True + d[x] = depth + for y in graph[x]: + if c[y]: # 이미 깊이를 구했다면 넘기기 + continue + parent[y][0] = x + dfs(y, depth + 1) + +# 전체 부모 관계를 설정하는 함수 +def set_parent(): + dfs(1, 0) # 루트 노드는 1번 노드 + for i in range(1, LOG): + for j in range(1, n + 1): + parent[j][i] = parent[parent[j][i - 1]][i - 1] + +# A와 B의 최소 공통 조상을 찾는 함수 +def lca(a, b): + # b가 더 깊도록 설정 + if d[a] > d[b]: + a, b = b, a + # 먼저 깊이(depth)가 동일하도록 + for i in range(LOG - 1, -1, -1): + if d[b] - d[a] >= (1 << i): + b = parent[b][i] + # 부모가 같아지도록 + if a == b: + return a; + for i in range(LOG - 1, -1, -1): + # 조상을 향해 거슬러 올라가기 + if parent[a][i] != parent[b][i]: + a = parent[a][i] + b = parent[b][i] + # 이후에 부모가 찾고자 하는 조상 + return parent[a][0] + +set_parent() + +m = int(input()) + +for i in range(m): + a, b = map(int, input().split()) + print(lca(a, b)) From 306a39740352b856ff02f100e4e9fba352f83e78 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:29:45 +0900 Subject: [PATCH 53/68] Update 6.cpp --- 21/6.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/21/6.cpp b/21/6.cpp index e69de29..3a9bf4e 100644 --- a/21/6.cpp +++ b/21/6.cpp @@ -0,0 +1,76 @@ +#include +#define MAX 100001 +#define LOG 21 // 2^20 = 1,000,000 + +using namespace std; + +int n, m; +int parent[MAX][LOG]; // 부모에 대한 정보 +int d[MAX]; // 각 노드까지의 깊이(depth) +int c[MAX]; // 각 노드의 깊이가 계산되었는지 여부 +vector graph[MAX]; // 그래프(graph) 정보 + +// 루트 노드부터 시작하여 깊이(depth)를 구하는 함수 +void dfs(int x, int depth) { + c[x] = true; + d[x] = depth; + for (int i = 0; i < graph[x].size(); i++) { + int y = graph[x][i]; + if (c[y]) continue; // 이미 깊이를 구했다면 넘기기 + parent[y][0] = x; + dfs(y, depth + 1); + } +} + +// 전체 부모 관계를 설정하는 함수 +void setParent() { + dfs(1, 0); // 루트 노드는 1번 노드 + for (int i = 1; i < LOG; i++) { + for (int j = 1; j <= n; j++) { + parent[j][i] = parent[parent[j][i - 1]][i - 1]; + } + } +} + +// A와 B의 최소 공통 조상을 찾는 함수 +int lca(int a, int b) { + // y가 더 깊도록 설정 + if(d[a] > d[b]) { + swap(a, b); + } + // 먼저 깊이(depth)가 동일하도록 + for(int i = LOG - 1; i >= 0; i--) { + if(d[b] - d[a] >= (1 << i)) { + b = parent[b][i]; + } + } + // 부모가 같아지도록 + if(a == b) return a; + for(int i = LOG - 1; i >= 0; i--) { + // 조상을 향해 거슬러 올라가기 + if(parent[a][i] != parent[b][i]) { + a = parent[a][i]; + b = parent[b][i]; + } + } + // 이후에 부모가 찾고자 하는 조상 + return parent[a][0]; +} + +int main() { + scanf("%d", &n); + for (int i = 0; i < n - 1; i++) { + int a, b; + scanf("%d %d", &a, &b); + graph[a].push_back(b); + graph[b].push_back(a); + } + setParent(); + + cin >> m; + for (int i = 0; i < m; i++) { + int a, b; + scanf("%d %d", &a, &b); + printf("%d\n", lca(a, b)); + } +} From 0c4ceceaaef6d8c27a3b591976739c9dcf503b30 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:39:14 +0900 Subject: [PATCH 54/68] Update 4.py --- 21/4.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/21/4.py b/21/4.py index e69de29..fcbcf02 100644 --- a/21/4.py +++ b/21/4.py @@ -0,0 +1,49 @@ +import sys +input = sys.stdin.readline +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 + +# 노드의 개수, 간선의 개수를 입력받기 +n, m = map(int, input().split()) +# 모든 간선에 대한 정보를 담는 리스트 만들기 +edges = [] +# 최단 거리 테이블을 모두 무한으로 초기화 +distance = [INF] * (n + 1) + +# 모든 간선 정보를 입력받기 +for _ in range(m): + a, b, c = map(int, input().split()) + # a번 노드에서 b번 노드로 가는 비용이 c라는 의미 + edges.append((a, b, c)) + +def bf(start): + # 시작 노드에 대해서 초기화 + distance[start] = 0 + # 전체 n - 1번의 라운드(round)를 반복 + for i in range(n): + # 매 반복마다 "모든 간선"을 확인하며 + for j in range(m): + cur_node = edges[j][0] + next_node = edges[j][1] + edge_cost = edges[j][2] + # 현재 간선을 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우 + if distance[cur_node] != INF and distance[next_node] > distance[cur_node] + edge_cost: + distance[next_node] = distance[cur_node] + edge_cost + # n번째 라운드에서도 값이 갱신된다면 음수 순환이 존재 + if i == n - 1: + return True + return False + +# 벨만 포드 알고리즘을 수행 +negative_cycle = bf(1) # 1번 노드가 시작 노드 + +if negative_cycle: + print("-1") +else: + # 1번 노드를 제외한 다른 모든 노드로 가기 위한 최단 거리를 출력 + for i in range(2, n + 1): + # 도달할 수 없는 경우, -1을 출력 + if distance[i] == INF: + print("-1") + # 도달할 수 있는 경우 거리를 출력 + else: + print(distance[i]) From 67d2fac5c362f50360077ea2bbda8dc2971e571b Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:40:27 +0900 Subject: [PATCH 55/68] Update 4.cpp --- 21/4.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/21/4.cpp b/21/4.cpp index e69de29..4640b85 100644 --- a/21/4.cpp +++ b/21/4.cpp @@ -0,0 +1,67 @@ +#include +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M) +// 노드의 개수는 최대 500개라고 가정 +int n, m; +// 모든 간선에 대한 정보를 담는 리스트 만들기 +vector > > edges; +// 최단 거리 테이블 만들기 +long long d[501]; // 오버 플로우 및 언더 플로우 방지 + +bool bf(int start) { + // 시작 노드에 대해서 초기화 + d[start] = 0; + // 전체 n - 1번의 라운드(round)를 반복 + for (int i = 0; i < n; i++) { + // 매 반복마다 "모든 간선"을 확인하며 + for (int j = 0; j < m; j++) { + int cur_node = edges[j].first; + int next_node = edges[j].second.first; + int edge_cost = edges[j].second.second; + // 현재 간선을 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우 + if (d[cur_node] != INF and d[next_node] > d[cur_node] + edge_cost) { + d[next_node] = d[cur_node] + edge_cost; + // n번째 라운드에서도 값이 갱신된다면 음수 순환이 존재 + if (i == n - 1) return true; + } + } + } + return false; +} + +int main(void) { + cin >> n >> m; + + // 모든 간선 정보를 입력받기 + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + // a번 노드에서 b번 노드로 가는 비용이 c라는 의미 + edges.push_back({a, {b, c}}); + } + + // 최단 거리 테이블을 모두 무한으로 초기화 + fill_n(d, 501, INF); + + // 다익스트라 알고리즘을 수행 + bool negative_cycle = bf(1); // 1번 노드가 시작 노드 + + if (negative_cycle) { + cout << "-1" << '\n'; + return 0; + } + // 1번 노드를 제외한 다른 모든 노드로 가기 위한 최단 거리를 출력 + for (int i = 2; i <= n; i++) { + // 도달할 수 없는 경우, -1을 출력 + if (d[i] == INF) { + cout << "-1" << '\n'; + } + // 도달할 수 있는 경우 거리를 출력 + else { + cout << d[i] << '\n'; + } + } +} From 96fbaddce2348765d9e3e6b458b3ee0fb8115c6a Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:46:25 +0900 Subject: [PATCH 56/68] Update 3.py --- 21/3.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/21/3.py b/21/3.py index e69de29..333a733 100644 --- a/21/3.py +++ b/21/3.py @@ -0,0 +1,43 @@ +import sys +input = sys.stdin.readline + +# 데이터의 개수(n), 변경 횟수(m), 구간 합 계산 횟수(k) +n, m, k = map(int, input().split()) + +# 전체 데이터의 개수는 최대 1,000,000개 +arr = [0] * (n + 1) +tree = [0] * (n + 1) + +# i번째 수까지의 누적 합을 계산하는 함수 +def prefix_sum(i): + result = 0 + while i > 0: + result += tree[i] + # 0이 아닌 마지막 비트만큼 빼가면서 이동 + i -= (i & -i) + return result + +# i번째 수를 dif만큼 더하는 함수 +def update(i, dif): + while i <= n: + tree[i] += dif + i += (i & -i) + +# start부터 end까지의 구간 합을 계산하는 함수 +def interval_sum(start, end): + return prefix_sum(end) - prefix_sum(start - 1) + +for i in range(1, n + 1): + x = int(input()) + arr[i] = x + update(i, x) + +for i in range(m + k): + a, b, c = map(int, input().split()) + # 업데이트(update) 연산인 경우 + if a == 1: + update(b, c - arr[b]) # 바뀐 크기(dif)만큼 적용 + arr[b] = c + # 구간 합(interval sum) 연산인 경우 + else: + print(interval_sum(b, c)) From 9d44cf43fdc32da202b551e3268eb83585c00b63 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:47:44 +0900 Subject: [PATCH 57/68] Update 3.cpp --- 21/3.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/21/3.cpp b/21/3.cpp index e69de29..1e78791 100644 --- a/21/3.cpp +++ b/21/3.cpp @@ -0,0 +1,62 @@ +#include + +using namespace std; + +// 전체 데이터의 개수는 최대 1,000,000개 +long long arr[1000001], tree[1000001]; +// 데이터의 개수(n), 변경 횟수(m), 구간 합 계산 횟수(k) +int n, m, k; + +// i번째 수까지의 누적 합을 계산하는 함수 +long long prefixSum(int i) { + long long result = 0; + while(i > 0) { + result += tree[i]; + // 0이 아닌 마지막 비트만큼 빼가면서 이동 + i -= (i & -i); + } + return result; +} + +// i번째 수를 dif만큼 더하는 함수 +void update(int i, long long dif) { + while(i <= n) { + tree[i] += dif; + i += (i & -i); + } +} + +// start부터 end까지의 구간 합을 계산하는 함수 +long long intervalSum(int start, int end) { + return prefixSum(end) - prefixSum(start - 1); +} + +int main(void) { + scanf("%d %d %d", &n, &m, &k); + for(int i = 1; i <= n; i++) { + long long x; + scanf("%lld", &x); + arr[i] = x; + update(i, x); + } + int count = 0; + while(count++ < m + k) { + int op; + scanf("%d", &op); + // 업데이트(update) 연산인 경우 + if(op == 1) { + int index; + long long value; + scanf("%d %lld", &index, &value); + update(index, value - arr[index]); // 바뀐 크기(dif)만큼 적용 + arr[index] = value; // i번째 수를 value로 업데이트 + } + // 구간 합(interval sum) 연산인 경우 + else { + int start, end; + scanf("%d %d", &start, &end); + printf("%lld\n", intervalSum(start, end)); + } + } + return 0; +} From 2d1423f96150b80d17673aedebfdaae21de4596c Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Mon, 2 Nov 2020 15:48:56 +0900 Subject: [PATCH 58/68] Update 4.cpp --- 21/4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/21/4.cpp b/21/4.cpp index 4640b85..5976efa 100644 --- a/21/4.cpp +++ b/21/4.cpp @@ -46,7 +46,7 @@ int main(void) { // 최단 거리 테이블을 모두 무한으로 초기화 fill_n(d, 501, INF); - // 다익스트라 알고리즘을 수행 + // 벨만 포드 알고리즘을 수행 bool negative_cycle = bf(1); // 1번 노드가 시작 노드 if (negative_cycle) { From ff7c99d07598160e2571ba9367e2c97547ed121f Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Thu, 31 Dec 2020 13:48:46 +0900 Subject: [PATCH 59/68] Update 11.java --- 5/11.java | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/5/11.java b/5/11.java index 66ddff0..9350caf 100644 --- a/5/11.java +++ b/5/11.java @@ -2,20 +2,20 @@ class Node { - private int index; - private int distance; + private int x; + private int y; - public Node(int index, int distance) { - this.index = index; - this.distance = distance; + public Node(int x, int y) { + this.x = x; + this.y = y; } - public int getIndex() { - return this.index; + public int getX() { + return this.x; } - public int getDistance() { - return this.distance; + public int getY() { + return this.y; } } @@ -35,8 +35,8 @@ public static int bfs(int x, int y) { // 큐가 빌 때까지 반복하기 while(!q.isEmpty()) { Node node = q.poll(); - x = node.getIndex(); - y = node.getDistance(); + x = node.getX(); + y = node.getY(); // 현재 위치에서 4가지 방향으로의 위치 확인 for (int i = 0; i < 4; i++) { int nx = x + dx[i]; @@ -76,4 +76,4 @@ public static void main(String[] args) { System.out.println(bfs(0, 0)); } -} \ No newline at end of file +} From 9a795c9ef527d21e216dbf4f8052f1f58a4d83a4 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 04:55:57 +0900 Subject: [PATCH 60/68] Update README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 65a62b3..8adf9d3 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,20 @@
+### 대기업 코딩 테스트 문제 적중 관련 + +* 최근 2021 K사 공채 코딩 테스트 1차 합격 커트라인은 3문제 ~ 3.5문제(부분점수 포함)로 예상됩니다. +* 저자 또한 코딩 테스트에 참여해 보았고, 파이썬만 이용하여 알고리즘 코딩 테스트에 합격할 수 있었습니다. +* 특히 아래 두 문제는 본 책의 파이썬 코드를 참고하여 쉽게 해결할 수 있었습니다. + +* 3번 문제 (이진 탐색): 책의 15장 [정렬된 배열에서 특정 수의 개수 구하기](/15/1.py) 알고리즘을 활용하면 쉽게 풀 수 있는 문제였습니다. + * 파이썬의 bisect_left 함수를 활용합니다. +* 4번 (플로이드 워셜): 책의 9장 [미래 도시](/9/4.py) 문제와 접근 방법 및 아이디어가 사실상 동일한 문제입니다. + * 특정한 중간 지점을 거쳐 갈 때의 최단 경로 알고리즘으로 볼 수 있습니다. + * 저자 개인적으로도 이 문제는 보자마자 풀어서 7분 이내로 풀 수 있었습니다. + +
+ ### 도와주신 분들 * 베타 리뷰어 님들: 김민철, 안수빈, 정한길, 황성호 외 10분 From a64f0880d73875148a70fb58f02d33e3fc47d782 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:15:09 +0900 Subject: [PATCH 61/68] Update 3.py --- 15/3.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/15/3.py b/15/3.py index 2bb1ea6..70fbd00 100644 --- a/15/3.py +++ b/15/3.py @@ -7,12 +7,12 @@ array.append(int(input())) array.sort() # 이진 탐색 수행을 위해 정렬 수행 -start = array[1] - array[0] # 집의 좌표 중에 가장 작은 값 -end = array[-1] - array[0] # 집의 좌표 중에 가장 큰 값 +start = 1 # 가능한 최소 거리 차이(min gap) +end = array[-1] - array[0] # 가능한 최대 거리 차이(max gap) result = 0 while(start <= end): - mid = (start + end) // 2 # mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + mid = (start + end) // 2 # mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미 # 첫째 집에는 무조건 공유기를 설치한다고 가정 value = array[0] count = 1 From e3c1c194425afeb09d368cab3511e91b3f09b05e Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:15:39 +0900 Subject: [PATCH 62/68] Update 3.cpp --- 15/3.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/15/3.cpp b/15/3.cpp index abf7922..2752c15 100644 --- a/15/3.cpp +++ b/15/3.cpp @@ -18,12 +18,12 @@ int main() { // 이진 탐색 수행을 위해 정렬 수행 sort(arr.begin(), arr.end()); - int start = arr[1] - arr[0]; // 집의 좌표 중에 가장 작은 값 - int end = arr[n - 1] - arr[0]; // 집의 좌표 값 중에서 가장 큰 값 + int start = 1; // 가능한 최소 거리 차이(min gap) + int end = arr[n - 1] - arr[0]; // 가능한 최대 거리 차이(max gap) int result = 0; while (start <= end) { - // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + // mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미 int mid = (start + end) / 2; // 첫째 집에는 무조건 공유기를 설치한다고 가정 int value = arr[0]; From 4db68cf64b95a79f9adca5a63089664679ebbacf Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:16:32 +0900 Subject: [PATCH 63/68] Update 3.java --- 15/3.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/15/3.java b/15/3.java index b50e99d..f6fe5bd 100644 --- a/15/3.java +++ b/15/3.java @@ -17,12 +17,12 @@ public static void main(String[] args) { // 이진 탐색을 위해 정렬 수행 Collections.sort(arr); - int start = arr.get(1) - arr.get(0); // 집의 좌표 중에 가장 작은 값 - int end = arr.get(n - 1) - arr.get(0); // 집의 좌표 중에 가장 큰 값 + int start = 1; // 가능한 최소 거리 차이(min gap) + int end = arr.get(n - 1) - arr.get(0); // 가능한 최대 거리 차이(max gap) int result = 0; while (start <= end) { - // mid는 가장 인접한 두 공유기 사이의 거리(Gap)을 의미 + // mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미 int mid = (start + end) / 2; // 첫째 집에는 무조건 공유기를 설치한다고 가정 int value = arr.get(0); From 578340bed8a2e49bfd461c87f4a6d9d912a00fae Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:31:51 +0900 Subject: [PATCH 64/68] Update notice.md --- notice.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/notice.md b/notice.md index 0440783..9c26194 100644 --- a/notice.md +++ b/notice.md @@ -78,6 +78,13 @@ ### 초판 3쇄 +#### (369p) '공유기 설치' 문제의 모범답안 오류 + +* 모범답안의 start 변수를 초기화하는 부분에서 다음의 코드가 올바른 내용입니다. +``` +start = 1 # 가능한 최소 거리(min gap) +``` + #### (375p) '금광' 문제의 입력 조건 오류 * 각 위치에 매장된 금의 개수는 1 이상이 아닌 0 이상입니다. From 1e134b721a61eec97a5827c795fcec4c487ac557 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:32:32 +0900 Subject: [PATCH 65/68] Update 3.py --- 15/3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/15/3.py b/15/3.py index 70fbd00..574c194 100644 --- a/15/3.py +++ b/15/3.py @@ -7,8 +7,8 @@ array.append(int(input())) array.sort() # 이진 탐색 수행을 위해 정렬 수행 -start = 1 # 가능한 최소 거리 차이(min gap) -end = array[-1] - array[0] # 가능한 최대 거리 차이(max gap) +start = 1 # 가능한 최소 거리(min gap) +end = array[-1] - array[0] # 가능한 최대 거리(max gap) result = 0 while(start <= end): From 1459cf3e9c91589ba89834dd25fe69f6471fc72c Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:32:49 +0900 Subject: [PATCH 66/68] Update 3.cpp --- 15/3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/15/3.cpp b/15/3.cpp index 2752c15..b889665 100644 --- a/15/3.cpp +++ b/15/3.cpp @@ -18,8 +18,8 @@ int main() { // 이진 탐색 수행을 위해 정렬 수행 sort(arr.begin(), arr.end()); - int start = 1; // 가능한 최소 거리 차이(min gap) - int end = arr[n - 1] - arr[0]; // 가능한 최대 거리 차이(max gap) + int start = 1; // 가능한 최소 거리(min gap) + int end = arr[n - 1] - arr[0]; // 가능한 최대 거리(max gap) int result = 0; while (start <= end) { From 0cbfb4b97abab20191ca2937d7edb1c3f3cd3361 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:33:15 +0900 Subject: [PATCH 67/68] Update 3.java --- 15/3.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/15/3.java b/15/3.java index f6fe5bd..7e55cb6 100644 --- a/15/3.java +++ b/15/3.java @@ -17,8 +17,8 @@ public static void main(String[] args) { // 이진 탐색을 위해 정렬 수행 Collections.sort(arr); - int start = 1; // 가능한 최소 거리 차이(min gap) - int end = arr.get(n - 1) - arr.get(0); // 가능한 최대 거리 차이(max gap) + int start = 1; // 가능한 최소 거리(min gap) + int end = arr.get(n - 1) - arr.get(0); // 가능한 최대 거리(max gap) int result = 0; while (start <= end) { From 7c35923a691756ce162e4f343d80d21fb6450e24 Mon Sep 17 00:00:00 2001 From: Dongbin Na Date: Tue, 12 Jan 2021 05:33:45 +0900 Subject: [PATCH 68/68] Update notice.md --- notice.md | 1 + 1 file changed, 1 insertion(+) diff --git a/notice.md b/notice.md index 9c26194..68a47a4 100644 --- a/notice.md +++ b/notice.md @@ -83,6 +83,7 @@ * 모범답안의 start 변수를 초기화하는 부분에서 다음의 코드가 올바른 내용입니다. ``` start = 1 # 가능한 최소 거리(min gap) +end = array[-1] - array[0] # 가능한 최대 거리(max gap) ``` #### (375p) '금광' 문제의 입력 조건 오류