├── BOJ ├── BOJ_1065.cpp ├── BOJ_10814.cpp ├── BOJ_10828.cpp ├── BOJ_10845.cpp ├── BOJ_10869.cpp ├── BOJ_10872.cpp ├── BOJ_1110.cpp ├── BOJ_11723.cpp ├── BOJ_11729.cpp ├── BOJ_1330.cpp ├── BOJ_1436.cpp ├── BOJ_15649.cpp ├── BOJ_2108.cpp ├── BOJ_2167.cpp ├── BOJ_2231.cpp ├── BOJ_2346.cpp ├── BOJ_2439.cpp ├── BOJ_2581.cpp ├── BOJ_2753.cpp ├── BOJ_2839.cpp ├── BOJ_2869.cpp ├── BOJ_4344.cpp ├── BOJ_4948.cpp ├── BOJ_9663.cpp └── Readme.md ├── FastCampus ├── Data Structure │ ├── 01-Array.ipynb │ ├── 02-Queue.ipynb │ ├── 03-Stack.ipynb │ ├── 04_1-Linked-List.ipynb │ ├── 04_2-Linked-List.ipynb │ └── 05-Time-Complexity.ipynb └── Readme.md ├── README.md └── Softeer ├── Readme.md ├── assembly_line.cpp ├── classroom_assignment.cpp ├── frog_in_the_well.cpp ├── grade_average.cpp ├── map_making.cpp ├── safebreaker.cpp ├── smart_logistics.cpp ├── stepping_stone.cpp ├── transmission.cpp └── virus.cpp /BOJ/BOJ_1065.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_1065.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_10814.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_10814.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_10828.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_10828.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_10845.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_10845.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_10869.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | 7 | int num1 = 0; 8 | int num2 = 0; 9 | 10 | cin >> num1 >> num2; 11 | 12 | if((num1 > 10000) || (num1 < 0) || (num2 > 10000) || (num2 < 0)) { //조건에 맞는지 확인 13 | cout << "Please enter another number!" << endl; 14 | cin >> num1 >> num2; 15 | while(1) { 16 | if ((num1 > 10000) || (num1 < 0) || (num2 > 10000) || (num2 < 0)) { //조건에 맞으면 while문 안에서 수 update 17 | cout << "Please enter another number!" << endl; 18 | cin >> num1 >> num2; 19 | } 20 | else { //아니면 while문 탈출 21 | break; 22 | } 23 | } 24 | } 25 | 26 | cout << num1 + num2 << endl; 27 | cout << num1 - num2 << endl; 28 | cout << num1 * num2 << endl; 29 | cout << num1 / num2 << endl; 30 | cout << num1 % num2 << endl; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /BOJ/BOJ_10872.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_10872.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_1110.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_1110.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_11723.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_11723.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_11729.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_11729.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_1330.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_1330.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_1436.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_1436.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_15649.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_15649.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2108.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2108.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2167.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2167.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2231.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2231.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2346.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2346.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2439.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int num = 0; 7 | cin >> num; 8 | 9 | for (int i = num; i > 0; i--) { 10 | for (int j = 1; j < num+1; j++) { 11 | if (i <= j) { 12 | cout << "*"; 13 | } 14 | else { 15 | cout << " "; 16 | } 17 | } 18 | cout << endl; 19 | } 20 | } -------------------------------------------------------------------------------- /BOJ/BOJ_2581.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2581.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2753.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2753.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2839.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2839.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_2869.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_2869.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_4344.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_4344.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_4948.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_4948.cpp -------------------------------------------------------------------------------- /BOJ/BOJ_9663.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/BOJ/BOJ_9663.cpp -------------------------------------------------------------------------------- /BOJ/Readme.md: -------------------------------------------------------------------------------- 1 | ## BOJ 알고리즘을 풀면서 느낀 점 & 참고할 점 2 | 같은 유형의 알고리즘 문제를 풀 때, 조금 더 효율적으로 풀려고 메모를 해둔다. 3 | #### [BOJ_10872](https://www.acmicpc.net/problem/10872) - 펙토리얼 4 | - 시간 측정 및 시간 줄이기용 팁을 배울 수 있었다. 5 | - 재귀함수를 풀 때 return이 함수로 되는데 그대로 써 두자. 6 | 그 함수가 나중에 무엇을 의미하는지만 알면 된다. 7 | 8 | #### [BOJ_11729](https://www.acmicpc.net/problem/11729) - 하노이 탑 이동 순서 9 | - 재귀함수.. 너무 어렵다... 언제 재귀함수를 써야 하나? 10 | 1. 무언가 같은 내용이 반복된다. 11 | 2. 일정한 순서대로 반복되는 것이 아닌, 앞의 내용에 영향을 받아서 기준이 달라지며 반복된다. 12 | 3. 재귀함수를 의심해본다. 13 | 4. 커다란 로직을 최대한 작게 쪼개본다. 14 | 5. 최소한으로 쪼개진 단위에 일정한 규칙이 있고, 이 규칙이 큰 단위에도 그대로 적용된다. 15 | 6. 최소한의 규칙에 맞게 재귀함수를 짠다. 16 | 17 | - 출처 : [백준알고리즘_11729_재귀함수_하노이탑 이동 (C언어)](https://codevang.tistory.com/73) 18 | 19 | #### [BOJ_1436](https://www.acmicpc.net/problem/1436) - 영화감독 숌 20 | - 부루트포스 알고리즘 (완전 탐색) 21 | - 완전 탐색은 간단하게 생각하면 하나하나 샅샅이 뒤져보는 것이다. 22 | 그냥 하나하나 조건에 맞게 따져가며 풀어보자. 23 | 24 | - 숫자를 입력으로 받고, 각 자리의 수를 구할 때 방법 25 | 1. 나눗셈과 나머지를 이용 + 배열을 이용하면 간편 26 | 2. 아예 문자처럼 취급해서 배열로 이용 27 | 28 | - 출처 : [숫자의 각 자릿수 구하기 알고리즘](https://www.crocus.co.kr/399) 29 | [[알고리즘] 각 자릿수 구하기](https://travelbeeee.tistory.com/4) 30 | 31 | #### [BOJ_2231](https://www.acmicpc.net/problem/2231) - 분해합 32 | - 소수를 찾는 방법? 절반을 초과하는 숫자는 나올 수 가 없다. 33 | - 시간 측정의 중요성을 깨닫게 해준 문제, 벡터 예외처리를 잘하자! 34 | 35 | #### [BOJ_4948](https://www.acmicpc.net/problem/4948) - 베르트랑 공준 36 | - continue문 잘 알고쓰자... 37 | - 에라토스테네스의 해 38 | 1. 소수를 판별할 범위만큼 배열 할당 39 | 2. 2부터 시작해서 특정 수의 배수를 모두 지운다. 40 | 3. 2부터 남아 있는 수를 모두 출력 41 | 42 | - 출처 : [[C++] 소수 구하기 최적의 알고리즘 (2) - 에라토스테네스의 체](https://marobiana.tistory.com/91) 43 | 44 | #### [BOJ 4344](https://www.acmicpc.net/problem/4344) - 평균은 넘겠지 45 | - 동적할당 배열의 접근법에 대해서 알 수 있는 문제였다.. 46 | 47 | #### [BOJ 2839](https://www.acmicpc.net/problem/2839) - 설탕 배달 48 | - N을 5로 나누고 3으로 나눈다는 흐름은 맞지만 그 순서가 틀려 살짝 해맨 문제 49 | 50 | #### [BOJ_2869](https://www.acmicpc.net/problem/2869) - 달팽이는 올라가고 싶다 51 | - 숫자를 max로 했을 때 시간초과가 뜰 수 있다. 52 | - max로 넣었을 때 시간초과가 나는지 안나는지 확인 할 것 53 | - 함수 하나로 해결 할 수 있다! 규칙을 잘 살펴보자. 54 | 55 | #### [BOJ_10814](https://www.acmicpc.net/problem/10814) - 나이순 정렬 56 | - 문제를 보자마자 우선순위 큐로 풀려고 했지만, 구글링을 통해 STL 라이브러리를 사용... 57 | - 코테에서 처음으로 클래스를 사용하여 푼 문제다. 58 | - sort()와 stable_sort()의 차이점을 알 수 있는 문제였다. 59 | 60 | #### [BOJ_2108](https://www.acmicpc.net/problem/2108) - 통계학 61 | - 벡터와 sort()를 이용해서 풀 수 있었던 문제 62 | - 최빈값을 구할 때 pair을 이용해서 간단하게 해결할 수 있었다. 63 | - 출처 : [[STL] vector 벡터 정리 및 예제](https://hyeonstorage.tistory.com/324) 64 | [[C++] Pair 클래스 정리 및 예제 (vector, sort)](https://blockdmask.tistory.com/64) 65 | [[백준 2108] 통계학 (최빈값, 산술평균, 중앙값, 범위)](https://blockdmask.tistory.com/113) 66 | 67 | #### [BOJ_15649](https://www.acmicpc.net/problem/15649) - N과 M (1) 68 | - 벡트레킹에 대한 첫번째 문제였다. 69 | - 벡트레킹을 구현하는 방법 중 모든 방법을 탐색하는데 재귀함수를 이용, 70 | 조건에서 맞지 않는 방법은 탐색하지 않는 방법을 택했다. 71 | - 이런 생각을 하기까지 많은 시간이 걸렸다. 72 | - 실제 숫자를 담을 배열과 그 곳을 방문했다는 것을 Check할 배열 2가지를 만드는 것으로 Start! 73 | - cnt를 증가시켜 재귀함수를 사용하자 -> 무언가가 일정하게 반복된다? 재귀함수! 74 | - 조건에 맞지 않으면 탐색하지 말자. 75 | - 출처 : [BOJ 15649. N과 M (1)](https://velog.io/@polynomeer/BOJ-1564957.-N%EA%B3%BC-M-18) 76 | 77 | #### [BOJ_9663](https://www.acmicpc.net/problem/9663) - N-Queen 78 | - 벡트레킹 = 완전 탐색 + 가지치기 79 | - 문제에는 2차원 행렬을 이용하는 것처럼 말을 했지만, 80 | 사실 1차원 행렬로도 충분히 풀 수 있는 문제였다. 81 | - 이번 문제도 시간이 오래 걸렸다... 82 | - 출처 : [9663번 N-QUEEN C++ 풀이](https://cryptosalamander.tistory.com/58) 83 | 84 | #### [BOJ_2167](https://www.acmicpc.net/problem/2167) - 2차원 배열의 합 85 | - 2차원 배열 동적할당에 대한 문제 86 | - 동적할당을 만들 때 arr[행][열] 이렇게 접근을 하자. 87 | - **행 - row, 열 - col** : 항상 헷갈린다.. 88 | - 출처 : [How do I declare a 2d array in C++ using new?](https://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new) 89 | 90 | #### [BOJ_10845](https://www.acmicpc.net/problem/10845) - 큐 91 | - 기본적인 자료구조 Queue를 직접 구현하는 문제 92 | - C++은 문자열 split을 직접 해주는 함수가 없으므로 구현을 하자. 93 | - 배열을 이용하여 인덱스를 사용하여 원소에 접근하면 크게 어려운 문제는 아니였다. 94 | - 출처 : [[C++] string 문자열 나누는 split](https://ssungkang.tistory.com/entry/C-string-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%98%EB%88%84%EB%8A%94-split) 95 | 96 | #### [BOJ_10828](https://www.acmicpc.net/problem/10828) - 스택 97 | - 앞서 풀어본 큐와 매우 유사한 문제이다. 98 | - 큐와 스택의 기본적인 차이점에 대해서 알 수 있던 문제였다. 99 | 100 | #### [BOJ_2346](https://www.acmicpc.net/problem/2346) - 풍선 터뜨리기 101 | - 처음 이 문제를 보자마자 생각 난 자료구조는 **원형 연결 리스트**이다. 102 | - 원형 연결 리스트를 구현해서 이 문제를 풀어야 하나 생각했지만, 조금의 trick을 생각해냈다. 103 | - deque를 이용하여 리스트를 표현하고 원소들의 순서를 바꾸어 내는 아이디어가 더 간단해보였다. 104 | - Deque는 vector 자료구조의 단점을 보완하기 위해 나온 Container이다. 105 | - 출처 : [BOJ : 2346 풍선 터뜨리기](https://deliorange.tistory.com/48) 106 | [[C++] deque container 정리 및 사용법](https://blockdmask.tistory.com/73) 107 | [[C++] Pair 클래스 정리 및 예제 (vector, sort)](https://blockdmask.tistory.com/64) 108 | 109 | #### [BOJ_11723](https://www.acmicpc.net/problem/11723) - 집합 110 | - 문제의 의도를 파악하지는 못했지만 꾸역꾸역 맞춘 문제 111 | - endl보단 "\n"으로! 속도 차이가 꽤 난다. 112 | - 비트마스크에 대해서 알 수 있었던 문제 113 | - 출처 : [[백준] 11723번 집합 - C++ 비트마스크](https://donggoolosori.github.io/2020/09/24/boj-11723/) 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/01-Array.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 꼭 알아둬야 할 자료구조 배열 (Array)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- 데이터를 나열하고, 각 데이터를 인덱스에 대응하도록 구성한 데이터 구조 \n", 15 | "- 파이썬에서는 리스트 타입이 배열 기능을 제공하고 있음" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "### 1. 배열이 필요한 이유?\n", 23 | "\n", 24 | "- 같은 종류의 데이터를 효율적으로 관리하기 위해 사용 \n", 25 | "- 같은 종류의 데이터를 순차적으로 저장 \n", 26 | "\n", 27 | "#### 배열의 장점 \n", 28 | "- 인덱스를 통한 빠른 접근이 가능 \n", 29 | "\n", 30 | "#### 배열의 단점\n", 31 | "- 배열을 한 번 만들어 놓았을 때, 원소들이 꽉 차면 추가가 어려움 \n", 32 | "- 삭제할 때, 데이터 공간을 따로 만들어야 함 " 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "### 2. C언어 vs Python" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "- C언어" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "#include \n", 56 | "\n", 57 | "int main(int argc, char * argv[]) \n", 58 | "{ \n", 59 | "\n", 60 | " char country[3] = \"US\"; // 공간을 미리 선언 \n", 61 | " printf (\"%c%c\\n\", country[0], country[1]); \n", 62 | " printf (\"%s\\n\", country); \n", 63 | " return 0; \n", 64 | "} " 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "- Python" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 1, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "US\n" 84 | ] 85 | } 86 | ], 87 | "source": [ 88 | "country = 'US'\n", 89 | "print (country)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "### 3. 파이썬과 배열" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 2, 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "text/plain": [ 107 | "[1, 2, 3, 4, 5]" 108 | ] 109 | }, 110 | "execution_count": 2, 111 | "metadata": {}, 112 | "output_type": "execute_result" 113 | } 114 | ], 115 | "source": [ 116 | "# 1차원 배열 리스트로 구현시\n", 117 | "data = [1,2,3,4,5]\n", 118 | "data" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 3, 124 | "metadata": {}, 125 | "outputs": [ 126 | { 127 | "data": { 128 | "text/plain": [ 129 | "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]" 130 | ] 131 | }, 132 | "execution_count": 3, 133 | "metadata": {}, 134 | "output_type": "execute_result" 135 | } 136 | ], 137 | "source": [ 138 | "# 2차원 배열 리스트로 구현시\n", 139 | "data = [[1,2,3],[4,5,6],[7,8,9]]\n", 140 | "data" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 4, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "[1, 2, 3]\n" 153 | ] 154 | } 155 | ], 156 | "source": [ 157 | "print(data[0])" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 5, 163 | "metadata": {}, 164 | "outputs": [ 165 | { 166 | "name": "stdout", 167 | "output_type": "stream", 168 | "text": [ 169 | "1\n" 170 | ] 171 | } 172 | ], 173 | "source": [ 174 | "print(data[0][0])" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "### 4. 프로그래밍 연습" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "metadata": {}, 187 | "source": [ 188 | "**연습1: 위의 2차원 배열에서 9, 8, 7 을 순서대로 출력해보기**" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": 6, 194 | "metadata": {}, 195 | "outputs": [ 196 | { 197 | "name": "stdout", 198 | "output_type": "stream", 199 | "text": [ 200 | "9 8 7\n" 201 | ] 202 | } 203 | ], 204 | "source": [ 205 | "print(data[2][2], data[2][1], data[2][0])" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 7, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "dataset = ['Braund, Mr. Owen Harris',\n", 215 | "'Cumings, Mrs. John Bradley (Florence Briggs Thayer)',\n", 216 | "'Heikkinen, Miss. Laina',\n", 217 | "'Futrelle, Mrs. Jacques Heath (Lily May Peel)',\n", 218 | "'Allen, Mr. William Henry',\n", 219 | "'Moran, Mr. James',\n", 220 | "'McCarthy, Mr. Timothy J',\n", 221 | "'Palsson, Master. Gosta Leonard',\n", 222 | "'Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)',\n", 223 | "'Nasser, Mrs. Nicholas (Adele Achem)',\n", 224 | "'Sandstrom, Miss. Marguerite Rut',\n", 225 | "'Bonnell, Miss. Elizabeth',\n", 226 | "'Saundercock, Mr. William Henry',\n", 227 | "'Andersson, Mr. Anders Johan',\n", 228 | "'Vestrom, Miss. Hulda Amanda Adolfina',\n", 229 | "'Hewlett, Mrs. (Mary D Kingcome) ',\n", 230 | "'Rice, Master. Eugene',\n", 231 | "'Williams, Mr. Charles Eugene',\n", 232 | "'Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)',\n", 233 | "'Masselmani, Mrs. Fatima',\n", 234 | "'Fynney, Mr. Joseph J',\n", 235 | "'Beesley, Mr. Lawrence',\n", 236 | "'McGowan, Miss. Anna \"Annie\"',\n", 237 | "'Sloper, Mr. William Thompson',\n", 238 | "'Palsson, Miss. Torborg Danira',\n", 239 | "'Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)',\n", 240 | "'Emir, Mr. Farred Chehab',\n", 241 | "'Fortune, Mr. Charles Alexander',\n", 242 | "'Dwyer, Miss. Ellen \"Nellie\"',\n", 243 | "'Todoroff, Mr. Lalio']" 244 | ] 245 | }, 246 | { 247 | "cell_type": "markdown", 248 | "metadata": {}, 249 | "source": [ 250 | "**연습2: 위의 dataset 리스트에서 전체 이름 안에 M 은 몇 번 나왔는지 빈도수 출력하기**" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 8, 256 | "metadata": {}, 257 | "outputs": [ 258 | { 259 | "name": "stdout", 260 | "output_type": "stream", 261 | "text": [ 262 | "30\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "cnt = 0\n", 268 | "for word in dataset:\n", 269 | " tmp = word.find('M') # find() - str에서 특정 문자를 찾고 위치를 반환 - 이렇게 하면 한 문자열에 M이 두개인 경우 파악 못함....\n", 270 | " if tmp != -1:\n", 271 | " cnt += 1\n", 272 | "print(cnt)" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "- 배열의 인덱스로 접근하자" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": 9, 285 | "metadata": {}, 286 | "outputs": [ 287 | { 288 | "name": "stdout", 289 | "output_type": "stream", 290 | "text": [ 291 | "38\n" 292 | ] 293 | } 294 | ], 295 | "source": [ 296 | "cnt = 0\n", 297 | "for data in dataset:\n", 298 | " for index in range(len(data)):\n", 299 | " if data[index] is 'M':\n", 300 | " cnt += 1\n", 301 | "print(cnt)" 302 | ] 303 | } 304 | ], 305 | "metadata": { 306 | "kernelspec": { 307 | "display_name": "Python 3", 308 | "language": "python", 309 | "name": "python3" 310 | }, 311 | "language_info": { 312 | "codemirror_mode": { 313 | "name": "ipython", 314 | "version": 3 315 | }, 316 | "file_extension": ".py", 317 | "mimetype": "text/x-python", 318 | "name": "python", 319 | "nbconvert_exporter": "python", 320 | "pygments_lexer": "ipython3", 321 | "version": "3.7.9" 322 | } 323 | }, 324 | "nbformat": 4, 325 | "nbformat_minor": 4 326 | } 327 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/02-Queue.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 꼭 알아둬야 할 자료구조 : 큐 (Queue)\n", 8 | "\n", 9 | "### 1. 큐 구조\n", 10 | "- **가장 먼저 넣은 데이터를 가장 먼저 꺼낼 수 있는 구조** \n", 11 | " - FIFO(First In, First Out) 또는 LILO(Last In, Last Out)방식으로 스택과는 꺼내는 순서가 반대 \n", 12 | "\n", 13 | "\n", 14 | " \n", 15 | "* 출처: http://www.stoimen.com/blog/2012/06/05/computer-algorithms-stack-and-queue-data-structure/ \n" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "### 2. 알아둘 용어 \n", 23 | "* Enqueue: 큐에 데이터를 넣는 기능\n", 24 | "* Dequeue: 큐에서 데이터를 꺼내는 기능\n", 25 | "* Visualgo 사이트에서 시연해보며 이해하기 (enqueue/dequeue 만 클릭해보며): https://visualgo.net/en/list" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "### 3. 파이썬 queue 라이브러리 활용해서 큐 자료 구조 사용하기\n", 33 | "* **queue 라이브러리에는 다양한 큐 구조로 Queue(), LifoQueue(), PriorityQueue() 제공**\n", 34 | "* 프로그램을 작성할 때 프로그램에 따라 적합한 자료 구조를 사용\n", 35 | " - Queue(): 가장 일반적인 큐 자료 구조\n", 36 | " - LifoQueue(): 나중에 입력된 데이터가 먼저 출력되는 구조 (스택 구조라고 보면 됨)\n", 37 | " - PriorityQueue(): 데이터마다 우선순위를 넣어서, 우선순위가 높은 순으로 데이터 출력\n", 38 | " \n", 39 | "> 일반적인 큐 외에 다양한 정책이 적용된 큐들이 있음" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "#### 3.1. Queue()로 큐 만들기 (가장 일반적인 큐, FIFO(First-In, First-Out))" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 1, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "import queue \n", 56 | "\n", 57 | "data_queue = queue.Queue() # 일반적인 큐가 만들어 진다(FIFO)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "#### Queue 라이브러리에서 Enqueue()는 put()으로 구현" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 2, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "data_queue.put(5)\n", 74 | "data_queue.put(\"coding\")" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 3, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "data": { 84 | "text/plain": [ 85 | "2" 86 | ] 87 | }, 88 | "execution_count": 3, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "data_queue.qsize() # queue size확인" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "#### Queue 라이브러리에서 Dequeue()는 get()으로 구현" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 4, 107 | "metadata": {}, 108 | "outputs": [ 109 | { 110 | "data": { 111 | "text/plain": [ 112 | "5" 113 | ] 114 | }, 115 | "execution_count": 4, 116 | "metadata": {}, 117 | "output_type": "execute_result" 118 | } 119 | ], 120 | "source": [ 121 | "data_queue.get() # 먼저 들어간 원소를 get()" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 5, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "data": { 131 | "text/plain": [ 132 | "1" 133 | ] 134 | }, 135 | "execution_count": 5, 136 | "metadata": {}, 137 | "output_type": "execute_result" 138 | } 139 | ], 140 | "source": [ 141 | "data_queue.qsize() # queue size확인" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "#### 3.2. LifoQueue()로 큐 만들기 (LIFO(Last-In, First-Out)) \n", 149 | "- 마지막에 넣은 원소가 가장 먼저 나온다. " 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 6, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "import queue\n", 159 | "data_queue = queue.LifoQueue()" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 7, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "data_queue.put(5)\n", 169 | "data_queue.put(\"coding\")" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 8, 175 | "metadata": {}, 176 | "outputs": [ 177 | { 178 | "data": { 179 | "text/plain": [ 180 | "2" 181 | ] 182 | }, 183 | "execution_count": 8, 184 | "metadata": {}, 185 | "output_type": "execute_result" 186 | } 187 | ], 188 | "source": [ 189 | "data_queue.qsize() # queue size확인" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 9, 195 | "metadata": {}, 196 | "outputs": [ 197 | { 198 | "data": { 199 | "text/plain": [ 200 | "'coding'" 201 | ] 202 | }, 203 | "execution_count": 9, 204 | "metadata": {}, 205 | "output_type": "execute_result" 206 | } 207 | ], 208 | "source": [ 209 | "data_queue.get() # 먼저 들어간 원소를 get()" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 10, 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "data": { 219 | "text/plain": [ 220 | "1" 221 | ] 222 | }, 223 | "execution_count": 10, 224 | "metadata": {}, 225 | "output_type": "execute_result" 226 | } 227 | ], 228 | "source": [ 229 | "data_queue.qsize() # queue size확인" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "#### 3.3. PriorityQueue()로 큐 만들기\n", 237 | "- 데이터를 넣을 때 우선순위에 따라서 데이터의 순서가 결정된다. " 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 11, 243 | "metadata": {}, 244 | "outputs": [], 245 | "source": [ 246 | "import queue\n", 247 | "data_queue = queue.PriorityQueue()" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "데이터를 넣을 때 튜플을 이용해서 우선순위를 같이 알려줘야 한다. \n", 255 | "(우선순위, 넣을 원소)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 12, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [ 264 | "data_queue.put((10,5))\n", 265 | "data_queue.put((5,\"coding\"))\n", 266 | "data_queue.put((15,\"korea\"))" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 13, 272 | "metadata": {}, 273 | "outputs": [ 274 | { 275 | "data": { 276 | "text/plain": [ 277 | "3" 278 | ] 279 | }, 280 | "execution_count": 13, 281 | "metadata": {}, 282 | "output_type": "execute_result" 283 | } 284 | ], 285 | "source": [ 286 | "data_queue.qsize() # queue size확인" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": 14, 292 | "metadata": {}, 293 | "outputs": [ 294 | { 295 | "data": { 296 | "text/plain": [ 297 | "(5, 'coding')" 298 | ] 299 | }, 300 | "execution_count": 14, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "data_queue.get() # 먼저 들어간 원소를 get()" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "### 참고: 어디에 큐가 많이 쓰일까? \n", 314 | "- **멀티 태스킹을 위한 프로세스 스케쥴링 방식을 구현하기 위해 많이 사용됨 (운영체제 참조)**\n", 315 | "> 큐의 경우에는 장단점 보다는 (특별히 언급되는 장단점이 없음), 큐의 활용 예로 프로세스 스케쥴링 방식을 함께 이해해두는 것이 좋음" 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "### 4. 프로그래밍 연습 " 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "**연습1: 리스트 변수로 큐를 다루는 enqueue, dequeue 기능 구현해보기**" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 15, 335 | "metadata": {}, 336 | "outputs": [], 337 | "source": [ 338 | "queue_list = list()\n", 339 | "\n", 340 | "def enqueue(data):\n", 341 | " queue_list.append(data)\n", 342 | " \n", 343 | "def dequeue():\n", 344 | " data = queue_list[0] # 0번 인덱스 데이터를 반환하기 위해서\n", 345 | " del queue_list[0] # 0번 인덱스 데이터 삭제\n", 346 | " return data" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": 16, 352 | "metadata": {}, 353 | "outputs": [], 354 | "source": [ 355 | "for index in range(10):\n", 356 | " enqueue(index)" 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": 17, 362 | "metadata": {}, 363 | "outputs": [ 364 | { 365 | "data": { 366 | "text/plain": [ 367 | "10" 368 | ] 369 | }, 370 | "execution_count": 17, 371 | "metadata": {}, 372 | "output_type": "execute_result" 373 | } 374 | ], 375 | "source": [ 376 | "len(queue_list)" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 18, 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "data": { 386 | "text/plain": [ 387 | "0" 388 | ] 389 | }, 390 | "execution_count": 18, 391 | "metadata": {}, 392 | "output_type": "execute_result" 393 | } 394 | ], 395 | "source": [ 396 | "dequeue()" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": 19, 402 | "metadata": {}, 403 | "outputs": [ 404 | { 405 | "data": { 406 | "text/plain": [ 407 | "1" 408 | ] 409 | }, 410 | "execution_count": 19, 411 | "metadata": {}, 412 | "output_type": "execute_result" 413 | } 414 | ], 415 | "source": [ 416 | "dequeue()" 417 | ] 418 | } 419 | ], 420 | "metadata": { 421 | "kernelspec": { 422 | "display_name": "Python 3", 423 | "language": "python", 424 | "name": "python3" 425 | }, 426 | "language_info": { 427 | "codemirror_mode": { 428 | "name": "ipython", 429 | "version": 3 430 | }, 431 | "file_extension": ".py", 432 | "mimetype": "text/x-python", 433 | "name": "python", 434 | "nbconvert_exporter": "python", 435 | "pygments_lexer": "ipython3", 436 | "version": "3.7.9" 437 | } 438 | }, 439 | "nbformat": 4, 440 | "nbformat_minor": 4 441 | } 442 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/03-Stack.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 꼭 알아둬야 할 자료 구조: 스택 (Stack) \n", 8 | "- Queue와 유사한 자료구조 \n", 9 | "- Queue는 FIFO(First In First Out) 정책 \n", 10 | "- Stack은 LIFO(Last In First Out) 정책" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "### 1. 스택 구조\n", 18 | "* 스택은 LIFO(Last In, Fisrt Out) 또는 FILO(First In, Last Out) 데이터 관리 방식을 따름\n", 19 | " - LIFO: 마지막에 넣은 데이터를 가장 먼저 추출하는 데이터 관리 정책\n", 20 | " - FILO: 처음에 넣은 데이터를 가장 마지막에 추출하는 데이터 관리 정책\n", 21 | "\n", 22 | "\n", 23 | "* 대표적인 스택의 활용\n", 24 | " - **컴퓨터 내부의 프로세스 구조의 함수 동작 방식** \n", 25 | "\n", 26 | "\n", 27 | "* 주요 기능\n", 28 | " - push(): 데이터를 스택에 넣기\n", 29 | " - pop(): 데이터를 스택에서 꺼내기 \n", 30 | " \n", 31 | " \n", 32 | "* Visualgo 사이트에서 시연해보며 이해하기 (push/pop 만 클릭해보며): https://visualgo.net/en/list \n", 33 | "" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "### 2. 스택 구조와 프로세스 스택\n", 41 | "- 스택 구조는 프로세스 실행 구조의 가장 기본\n", 42 | " - 함수 호출시 프로세스 실행 구조를 스택과 비교해서 이해 필요" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "재귀 함수를 통해서 프로세스가 어떻게 실행되는지 이해해보기" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 1, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "# 재귀 함수\n", 59 | "def recursive(data):\n", 60 | " if data < 0:\n", 61 | " print(\"End!\")\n", 62 | " else:\n", 63 | " print(data)\n", 64 | " recursive(data-1)\n", 65 | " print(\"Returned\",data)" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 2, 71 | "metadata": {}, 72 | "outputs": [ 73 | { 74 | "name": "stdout", 75 | "output_type": "stream", 76 | "text": [ 77 | "4\n", 78 | "3\n", 79 | "2\n", 80 | "1\n", 81 | "0\n", 82 | "End!\n", 83 | "Returned 0\n", 84 | "Returned 1\n", 85 | "Returned 2\n", 86 | "Returned 3\n", 87 | "Returned 4\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "recursive(4)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "### 3. 자료 구조 스택의 장단점\n", 100 | "- 장점\n", 101 | " - 구조가 단순해서, 구현이 쉽다.\n", 102 | " - 데이터 저장/읽기 속도가 빠르다.\n", 103 | "- 단점 (일반적인 스택 구현시) \n", 104 | " - 데이터 최대 갯수를 미리 정해야 한다. \n", 105 | " - 파이썬의 경우 재귀 함수는 1000번까지만 호출이 가능함\n", 106 | " - 저장 공간의 낭비가 발생할 수 있음\n", 107 | " - 미리 최대 갯수만큼 저장 공간을 확보해야 함\n", 108 | "\n", 109 | "> 스택은 단순하고 빠른 성능을 위해 사용되므로, 보통 배열 구조를 활용해서 구현하는 것이 일반적임. \n", 110 | "> 이 경우, 위에서 열거한 단점이 있을 수 있음" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### 4. 파이썬 리스트 기능에서 제공하는 메서드로 스택 사용해보기\n", 118 | "* append(push), pop 메서드 제공" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 3, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "data_stack = list()\n", 128 | "\n", 129 | "data_stack.append(1)\n", 130 | "data_stack.append(2)" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 4, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "data": { 140 | "text/plain": [ 141 | "[1, 2]" 142 | ] 143 | }, 144 | "execution_count": 4, 145 | "metadata": {}, 146 | "output_type": "execute_result" 147 | } 148 | ], 149 | "source": [ 150 | "data_stack" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 5, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "2" 162 | ] 163 | }, 164 | "execution_count": 5, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "data_stack.pop()" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "### 5. 프로그래밍 연습 \n", 178 | "\n", 179 | "**연습1: 리스트 변수로 스택을 다루는 pop, push 기능 구현해보기 (pop, push 함수 사용하지 않고 직접 구현해보기)**" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 6, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "stack_list = list()\n", 189 | "\n", 190 | "def push(data):\n", 191 | " stack_list.append(data)\n", 192 | " \n", 193 | "def pop():\n", 194 | " data = stack_list[-1]\n", 195 | " del stack_list[-1] # data를 없애주기 위해서\n", 196 | " return data" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 7, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "# for문을 이용하여 stack에 push 해보기\n", 206 | "for index in range(10):\n", 207 | " push(index)" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 8, 213 | "metadata": {}, 214 | "outputs": [ 215 | { 216 | "data": { 217 | "text/plain": [ 218 | "9" 219 | ] 220 | }, 221 | "execution_count": 8, 222 | "metadata": {}, 223 | "output_type": "execute_result" 224 | } 225 | ], 226 | "source": [ 227 | "pop()" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 9, 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "data": { 237 | "text/plain": [ 238 | "8" 239 | ] 240 | }, 241 | "execution_count": 9, 242 | "metadata": {}, 243 | "output_type": "execute_result" 244 | } 245 | ], 246 | "source": [ 247 | "pop()" 248 | ] 249 | } 250 | ], 251 | "metadata": { 252 | "kernelspec": { 253 | "display_name": "Python 3", 254 | "language": "python", 255 | "name": "python3" 256 | }, 257 | "language_info": { 258 | "codemirror_mode": { 259 | "name": "ipython", 260 | "version": 3 261 | }, 262 | "file_extension": ".py", 263 | "mimetype": "text/x-python", 264 | "name": "python", 265 | "nbconvert_exporter": "python", 266 | "pygments_lexer": "ipython3", 267 | "version": "3.7.9" 268 | } 269 | }, 270 | "nbformat": 4, 271 | "nbformat_minor": 4 272 | } 273 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/04_1-Linked-List.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 꼭 알아둬야 할 자료 구조: 링크드 리스트 (Linked List)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### 1. 링크드 리스트 (Linked List) 구조\n", 15 | "* 연결 리스트라고도 함\n", 16 | "* 배열은 순차적으로 연결된 공간에 데이터를 나열하는 데이터 구조\n", 17 | "* 링크드 리스트는 떨어진 곳에 존재하는 데이터를 화살표로 연결해서 관리하는 데이터 구조\n", 18 | "* 본래 C언어에서는 주요한 데이터 구조이지만, 파이썬은 리스트 타입이 링크드 리스트의 기능을 모두 지원" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "* 링크드 리스트 기본 구조와 용어\n", 26 | " - 노드(Node): 데이터 저장 단위 (데이터값, 포인터) 로 구성\n", 27 | " - 포인터(pointer): 각 노드 안에서, 다음이나 이전의 노드와의 연결 정보를 가지고 있는 공간 \n", 28 | " - 데이터를 담을 공간과 다음 데이터를 가르키는 주소값(포인터)을 하나의 노드에 저장\n", 29 | "\n", 30 | "
\n", 31 | "* 일반적인 링크드 리스트 형태\n", 32 | "\n", 33 | "\n", 34 | "
(출처: wikipedia, https://en.wikipedia.org/wiki/Linked_list)
" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "#### 배열과 Linked List의 차이점\n", 42 | "\n", 43 | "- 배열은 미리 특정 공간을 선언 한 후, 인덱스로 접근 \n", 44 | "- Linked List는 필요할 때 마다 공간을 추가하여 연결 시키는 구조" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "### 2. 간단한 링크드 리스트 예" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "#### Node 구현\n", 59 | "- 보통 파이썬에서 링크드 리스트 구현시, 파이썬 클래스를 활용함" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 1, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "class Node:\n", 69 | " def __init__(self,data,next = None):\n", 70 | " self.data = data\n", 71 | " self.next = next" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "#### Node와 Node 연결하기 (포인터 활용)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 2, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "node1 = Node(1) # data 1, next = None\n", 88 | "node2 = Node(2) # data 2, next = None\n", 89 | "node1.next = node2 # node1 next를 이용하여 연결\n", 90 | "head = node1 # 맨 처음 노드를 알려줄 변수 선언" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "#### 링크드 리스트로 데이터 추가하기" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 3, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "class Node:\n", 107 | " def __init__(self,data,next=None):\n", 108 | " self.data = data\n", 109 | " self.next = next\n", 110 | " \n", 111 | "# 새로 들어온 원소를 마지막 노드에 추가하는 함수\n", 112 | "def add(data):\n", 113 | " new = Node(data)\n", 114 | " node = head\n", 115 | " \n", 116 | " while node.next: # 마지막 노드 찾기\n", 117 | " node = node.next\n", 118 | " \n", 119 | " node.next = new # 마지막 노드에 뒤에 새로운 노드 추가" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 4, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "node1 = Node(1)\n", 129 | "head = node1\n", 130 | "for index in range(2, 10):\n", 131 | " add(index)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "#### 링크드 리스트 데이터 출력하기(검색하기)" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": 5, 144 | "metadata": {}, 145 | "outputs": [ 146 | { 147 | "name": "stdout", 148 | "output_type": "stream", 149 | "text": [ 150 | "1\n", 151 | "2\n", 152 | "3\n", 153 | "4\n", 154 | "5\n", 155 | "6\n", 156 | "7\n", 157 | "8\n", 158 | "9\n" 159 | ] 160 | } 161 | ], 162 | "source": [ 163 | "node = head\n", 164 | "while node.next:\n", 165 | " print(node.data)\n", 166 | " node = node.next\n", 167 | "print (node.data)" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "### 3. 링크드 리스트의 장단점 (전통적인 C언어에서의 배열과 링크드 리스트)\n", 175 | "* 장점\n", 176 | " - 미리 데이터 공간을 미리 할당하지 않아도 됨\n", 177 | " - 배열은 **미리 데이터 공간을 할당** 해야 함\n", 178 | "* 단점\n", 179 | " - 연결을 위한 별도 데이터 공간이 필요하므로, 저장공간 효율이 높지 않음\n", 180 | " - 연결 정보를 찾는 시간이 필요하므로 접근 속도가 느림\n", 181 | " - 중간 데이터 삭제시, 앞뒤 데이터의 연결을 재구성해야 하는 부가적인 작업 필요" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "metadata": {}, 187 | "source": [ 188 | "### 4. 링크드 리스트의 복잡한 기능1 (링크드 리스트 데이터 사이에 데이터를 추가)\n", 189 | "- 링크드 리스트는 유지 관리에 부가적인 구현이 필요함\n", 190 | "\n", 191 | "\n", 192 | "
(출처: wikipedia, https://en.wikipedia.org/wiki/Linked_list)
" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "### 중간에 삽입하는 노드 만들기\n", 200 | "1. 삽입을 원하는 타겟 노드 찾기 (위의 예제로는 12) \n", 201 | "2. 타겟 노드에 연결되어 있는 주소(포인터)를 새 노드로 변경하기 \n", 202 | "3. 새 노드의 포인터를 이용하여 원래 노드를 연결하고 있던 노드(위의 예제로는 99)를 가르키도록 만들기" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "#### Linked List 출력" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 6, 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "name": "stdout", 219 | "output_type": "stream", 220 | "text": [ 221 | "1\n", 222 | "2\n", 223 | "3\n", 224 | "4\n", 225 | "5\n", 226 | "6\n", 227 | "7\n", 228 | "8\n", 229 | "9\n" 230 | ] 231 | } 232 | ], 233 | "source": [ 234 | "node = head\n", 235 | "while node.next:\n", 236 | " print(node.data)\n", 237 | " node = node.next\n", 238 | "print (node.data)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 7, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "node3 = Node(1.5) # 새로운 노드 만들기" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": 8, 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [ 256 | "node = head\n", 257 | "search = True\n", 258 | "\n", 259 | "while search: # 원하는 타겟 노드 찾기\n", 260 | " if node.data == 1:\n", 261 | " search = False\n", 262 | " else:\n", 263 | " node = node.next\n", 264 | "\n", 265 | "node_next = node.next # 타겟 노드의 원래 포인터가 가르키는 노드 임시 저장\n", 266 | "node.next = node3 # 새 노드를 타겟 노드 포인터가 가르키도록 변경\n", 267 | "node3.next = node_next # 새 노드의 포인터를 이용하여 원래 노드의 다음 노드를 가르키도록 변경 " 268 | ] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": {}, 273 | "source": [ 274 | "#### Linked List 출력" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 9, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "1\n", 287 | "1.5\n", 288 | "2\n", 289 | "3\n", 290 | "4\n", 291 | "5\n", 292 | "6\n", 293 | "7\n", 294 | "8\n", 295 | "9\n" 296 | ] 297 | } 298 | ], 299 | "source": [ 300 | "node = head\n", 301 | "while node.next:\n", 302 | " print(node.data)\n", 303 | " node = node.next\n", 304 | "print (node.data)" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "### 5. 파이썬 객체지향 프로그래밍으로 링크드 리스트 구현하기" 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "execution_count": 10, 317 | "metadata": {}, 318 | "outputs": [], 319 | "source": [ 320 | "class Node:\n", 321 | " def __init__(self,data,next = None):\n", 322 | " self.data = data\n", 323 | " self.next = next\n", 324 | "\n", 325 | "class NodeMgmt:\n", 326 | " def __init__(self,data):\n", 327 | " self.head = Node(data)\n", 328 | " \n", 329 | " def add(self, data):\n", 330 | " if self.head is None:\n", 331 | " self.head = Node(data)\n", 332 | " \n", 333 | " else:\n", 334 | " node = self.head\n", 335 | " while node.next:\n", 336 | " node = node.next\n", 337 | " \n", 338 | " node.next = Node(data)\n", 339 | " \n", 340 | " def print(self):\n", 341 | " node = self.head\n", 342 | " \n", 343 | " while node:\n", 344 | " print(node.data)\n", 345 | " node = node.next " 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 11, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "linkedlist1 = NodeMgmt(0)" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 12, 360 | "metadata": {}, 361 | "outputs": [ 362 | { 363 | "name": "stdout", 364 | "output_type": "stream", 365 | "text": [ 366 | "0\n" 367 | ] 368 | } 369 | ], 370 | "source": [ 371 | "linkedlist1.print()" 372 | ] 373 | }, 374 | { 375 | "cell_type": "code", 376 | "execution_count": 13, 377 | "metadata": {}, 378 | "outputs": [ 379 | { 380 | "name": "stdout", 381 | "output_type": "stream", 382 | "text": [ 383 | "0\n", 384 | "1\n", 385 | "2\n", 386 | "3\n", 387 | "4\n", 388 | "5\n", 389 | "6\n", 390 | "7\n", 391 | "8\n", 392 | "9\n" 393 | ] 394 | } 395 | ], 396 | "source": [ 397 | "for data in range(1,10):\n", 398 | " linkedlist1.add(data)\n", 399 | "linkedlist1.print()" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | "### 6. 링크드 리스트의 복잡한 기능2 (특정 노드를 삭제)\n", 407 | "* 다음 코드는 위의 코드에서 delete 메서드만 추가한 것이므로 해당 메서드만 확인하면 됨 \n", 408 | "\n", 409 | "\n", 410 | "- 특정노드를 삭제하는 경우의 수 \n", 411 | " 1. 첫번째 노드 삭제 \n", 412 | " 2. 마지막 노드 삭제 \n", 413 | " 3. 중간 노드 삭제 " 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": 14, 419 | "metadata": {}, 420 | "outputs": [], 421 | "source": [ 422 | "class Node:\n", 423 | " def __init__(self,data,next = None):\n", 424 | " self.data = data\n", 425 | " self.next = next\n", 426 | "\n", 427 | "class NodeMgmt:\n", 428 | " def __init__(self,data):\n", 429 | " self.head = Node(data)\n", 430 | " \n", 431 | " def add(self, data):\n", 432 | " if self.head is None:\n", 433 | " self.head = Node(data)\n", 434 | " \n", 435 | " else:\n", 436 | " node = self.head\n", 437 | " while node.next:\n", 438 | " node = node.next\n", 439 | " \n", 440 | " node.next = Node(data)\n", 441 | " \n", 442 | " def print(self):\n", 443 | " node = self.head\n", 444 | " \n", 445 | " while node:\n", 446 | " print(node.data)\n", 447 | " node = node.next \n", 448 | " \n", 449 | " def delete(self, data):\n", 450 | " if self.head is None:\n", 451 | " print(\"해당 값을 가지는 노드가 없습니다!\")\n", 452 | " return\n", 453 | " \n", 454 | " # 첫번째 노드 삭제\n", 455 | " if self.head.data == data:\n", 456 | " tmp = self.head\n", 457 | " self.head = self.head.next\n", 458 | " del tmp\n", 459 | " \n", 460 | " # 중간 노드 or 마지막 노드 삭제\n", 461 | " else:\n", 462 | " node = self.head\n", 463 | " while node.next:\n", 464 | " if node.next.data == data: # 다음 가르키고 있는 노드가 삭제하고 싶은 노드 일 때\n", 465 | " tmp = node.next\n", 466 | " node.next = node.next.next # 삭제하고 싶은 노드 다음으로 연결\n", 467 | " del tmp\n", 468 | " return\n", 469 | " else :\n", 470 | " node = node.next # 계속 다음 노드를 탐색\n", 471 | " \n", 472 | " def search_node(self, data):\n", 473 | " node = self.head\n", 474 | " \n", 475 | " while node:\n", 476 | " if node.data == data:\n", 477 | " return node\n", 478 | " \n", 479 | " else:\n", 480 | " node = node.next" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "### 예제를 통해 Test 해보기" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": 15, 493 | "metadata": {}, 494 | "outputs": [ 495 | { 496 | "name": "stdout", 497 | "output_type": "stream", 498 | "text": [ 499 | "0\n" 500 | ] 501 | } 502 | ], 503 | "source": [ 504 | "linkedlist1 = NodeMgmt(0)\n", 505 | "linkedlist1.print()" 506 | ] 507 | }, 508 | { 509 | "cell_type": "markdown", 510 | "metadata": {}, 511 | "source": [ 512 | "#### head 가 살아있음을 확인" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "execution_count": 16, 518 | "metadata": {}, 519 | "outputs": [ 520 | { 521 | "data": { 522 | "text/plain": [ 523 | "<__main__.Node at 0x1ccd3733808>" 524 | ] 525 | }, 526 | "execution_count": 16, 527 | "metadata": {}, 528 | "output_type": "execute_result" 529 | } 530 | ], 531 | "source": [ 532 | "linkedlist1.head" 533 | ] 534 | }, 535 | { 536 | "cell_type": "markdown", 537 | "metadata": {}, 538 | "source": [ 539 | "#### head 를 지워봄(위에서 언급한 경우의 수1)" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "execution_count": 17, 545 | "metadata": {}, 546 | "outputs": [], 547 | "source": [ 548 | "linkedlist1.delete(0)" 549 | ] 550 | }, 551 | { 552 | "cell_type": "markdown", 553 | "metadata": {}, 554 | "source": [ 555 | "#### 다음 코드 실행시 아무것도 안나온다는 것은 linkedlist1.head 가 정상적으로 삭제되었음을 의미" 556 | ] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "execution_count": 18, 561 | "metadata": {}, 562 | "outputs": [], 563 | "source": [ 564 | "linkedlist1.print()" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": {}, 570 | "source": [ 571 | "#### 다시 하나의 노드를 만들어봄 그리고 여러 개의 노드 추가" 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": 19, 577 | "metadata": {}, 578 | "outputs": [ 579 | { 580 | "name": "stdout", 581 | "output_type": "stream", 582 | "text": [ 583 | "0\n" 584 | ] 585 | } 586 | ], 587 | "source": [ 588 | "linkedlist1 = NodeMgmt(0)\n", 589 | "linkedlist1.print()" 590 | ] 591 | }, 592 | { 593 | "cell_type": "code", 594 | "execution_count": 20, 595 | "metadata": {}, 596 | "outputs": [ 597 | { 598 | "name": "stdout", 599 | "output_type": "stream", 600 | "text": [ 601 | "0\n", 602 | "1\n", 603 | "2\n", 604 | "3\n", 605 | "4\n", 606 | "5\n", 607 | "6\n", 608 | "7\n", 609 | "8\n", 610 | "9\n" 611 | ] 612 | } 613 | ], 614 | "source": [ 615 | "for data in range(1, 10):\n", 616 | " linkedlist1.add(data)\n", 617 | "linkedlist1.print()" 618 | ] 619 | }, 620 | { 621 | "cell_type": "markdown", 622 | "metadata": {}, 623 | "source": [ 624 | "#### 노드 중에 한개를 삭제함 (위에서 언급한 경우의 수2)" 625 | ] 626 | }, 627 | { 628 | "cell_type": "code", 629 | "execution_count": 21, 630 | "metadata": {}, 631 | "outputs": [], 632 | "source": [ 633 | "linkedlist1.delete(4)" 634 | ] 635 | }, 636 | { 637 | "cell_type": "markdown", 638 | "metadata": {}, 639 | "source": [ 640 | "#### 특정 노드가 삭제되었음을 알 수 있음" 641 | ] 642 | }, 643 | { 644 | "cell_type": "code", 645 | "execution_count": 22, 646 | "metadata": {}, 647 | "outputs": [ 648 | { 649 | "name": "stdout", 650 | "output_type": "stream", 651 | "text": [ 652 | "0\n", 653 | "1\n", 654 | "2\n", 655 | "3\n", 656 | "5\n", 657 | "6\n", 658 | "7\n", 659 | "8\n", 660 | "9\n" 661 | ] 662 | } 663 | ], 664 | "source": [ 665 | "linkedlist1.print()" 666 | ] 667 | }, 668 | { 669 | "cell_type": "code", 670 | "execution_count": 23, 671 | "metadata": {}, 672 | "outputs": [], 673 | "source": [ 674 | "linkedlist1.delete(9)" 675 | ] 676 | }, 677 | { 678 | "cell_type": "code", 679 | "execution_count": 24, 680 | "metadata": {}, 681 | "outputs": [ 682 | { 683 | "name": "stdout", 684 | "output_type": "stream", 685 | "text": [ 686 | "0\n", 687 | "1\n", 688 | "2\n", 689 | "3\n", 690 | "5\n", 691 | "6\n", 692 | "7\n", 693 | "8\n" 694 | ] 695 | } 696 | ], 697 | "source": [ 698 | "linkedlist1.print()" 699 | ] 700 | }, 701 | { 702 | "cell_type": "markdown", 703 | "metadata": {}, 704 | "source": [ 705 | "#### Search node 예제" 706 | ] 707 | }, 708 | { 709 | "cell_type": "code", 710 | "execution_count": 25, 711 | "metadata": {}, 712 | "outputs": [ 713 | { 714 | "name": "stdout", 715 | "output_type": "stream", 716 | "text": [ 717 | "4\n" 718 | ] 719 | } 720 | ], 721 | "source": [ 722 | "# 테스트\n", 723 | "node_mgmt = NodeMgmt(0)\n", 724 | "for data in range(1, 10):\n", 725 | " node_mgmt.add(data)\n", 726 | "\n", 727 | "node = node_mgmt.search_node(4)\n", 728 | "print (node.data)" 729 | ] 730 | } 731 | ], 732 | "metadata": { 733 | "kernelspec": { 734 | "display_name": "Python 3", 735 | "language": "python", 736 | "name": "python3" 737 | }, 738 | "language_info": { 739 | "codemirror_mode": { 740 | "name": "ipython", 741 | "version": 3 742 | }, 743 | "file_extension": ".py", 744 | "mimetype": "text/x-python", 745 | "name": "python", 746 | "nbconvert_exporter": "python", 747 | "pygments_lexer": "ipython3", 748 | "version": "3.7.9" 749 | } 750 | }, 751 | "nbformat": 4, 752 | "nbformat_minor": 4 753 | } 754 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/04_2-Linked-List.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### [04_1-Linked-List](https://github.com/Taeyoung96/Algorithm-study/blob/main/FastCampus/Data%20Structure/04_1-Linked-List.ipynb) 다음 진행되는 자료 입니다." 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### 7. 다양한 링크드 리스트 구조 \n", 15 | "* 더블 링크드 리스트(Doubly linked list) 기본 구조 \n", 16 | " - 이중 연결 리스트라고도 함\n", 17 | " - 장점: 양방향으로 연결되어 있어서 노드 탐색이 양쪽으로 모두 가능\n", 18 | "
\n", 19 | "\n", 20 | "
(출처: wikipedia, https://en.wikipedia.org/wiki/Linked_list)
" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "#### Linked List의 단점\n", 28 | "\n", 29 | "- 항상 앞에서부터 검색을 해야한다. \n", 30 | "- 다음 노드를 가르키는 포인터만 저장하고 있기 때문! \n", 31 | "- 이 단점을 보완하기 위해 만든 자료구조가 **Doubly Linked List**" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 1, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "class Node:\n", 41 | " def __init__(self,data,prev = None,next = None):\n", 42 | " self.data = data\n", 43 | " self.prev = None\n", 44 | " self.next = next\n", 45 | " \n", 46 | "class NodeMgmt:\n", 47 | " def __init__(self, data):\n", 48 | " self.head = Node(data)\n", 49 | " self.tail = Node(data)\n", 50 | " \n", 51 | " def insert(self, data):\n", 52 | " if self.head is None:\n", 53 | " self.head = Node(data)\n", 54 | " self.tail = Node(data)\n", 55 | " \n", 56 | " else:\n", 57 | " node = self.head\n", 58 | " while node.next: # 맨 마지막 노드 찾기\n", 59 | " node = node.next\n", 60 | " new = Node(data) \n", 61 | " node.next = new # 새로운 노드를 마지막 노드 다음으로 추가\n", 62 | " new.prev = node # 새로운 노드가 마지막 노드의 prev로 지정\n", 63 | " self.tail = new # tail update\n", 64 | " \n", 65 | " def print(self):\n", 66 | " node = self.head\n", 67 | " \n", 68 | " while node:\n", 69 | " print(node.data)\n", 70 | " node = node.next" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "#### 예제로 확인해보기" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 2, 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "name": "stdout", 87 | "output_type": "stream", 88 | "text": [ 89 | "0\n", 90 | "1\n", 91 | "2\n", 92 | "3\n", 93 | "4\n", 94 | "5\n", 95 | "6\n", 96 | "7\n", 97 | "8\n", 98 | "9\n" 99 | ] 100 | } 101 | ], 102 | "source": [ 103 | "double_linked_list = NodeMgmt(0)\n", 104 | "for data in range(1, 10):\n", 105 | " double_linked_list.insert(data)\n", 106 | " \n", 107 | "double_linked_list.print()" 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "**연습3: 위 코드에서 노드 데이터가 특정 숫자인 노드 앞에 데이터를 추가하는 함수를 만들고, 테스트해보기** \n", 115 | "- 더블 링크드 리스트의 tail 에서부터 뒤로 이동하며, 특정 숫자인 노드를 찾는 방식으로 함수를 구현하기\n", 116 | "- 테스트: 임의로 0 ~ 9까지 데이터를 링크드 리스트에 넣어보고, 데이터 값이 2인 노드 앞에 1.5 데이터 값을 가진 노드를 추가해보기" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 3, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "class Node:\n", 126 | " def __init__(self,data,prev = None,next = None):\n", 127 | " self.data = data\n", 128 | " self.prev = None\n", 129 | " self.next = next\n", 130 | " \n", 131 | "class NodeMgmt:\n", 132 | " def __init__(self, data):\n", 133 | " self.head = Node(data)\n", 134 | " self.tail = Node(data)\n", 135 | " \n", 136 | " def insert(self, data):\n", 137 | " if self.head is None:\n", 138 | " self.head = Node(data)\n", 139 | " self.tail = Node(data)\n", 140 | " \n", 141 | " else:\n", 142 | " node = self.head\n", 143 | " while node.next: # 맨 마지막 노드 찾기\n", 144 | " node = node.next\n", 145 | " new = Node(data) \n", 146 | " node.next = new # 새로운 노드를 마지막 노드 다음으로 추가\n", 147 | " new.prev = node # 새로운 노드가 마지막 노드의 prev로 지정\n", 148 | " self.tail = new # tail update\n", 149 | " \n", 150 | " def print(self):\n", 151 | " node = self.head\n", 152 | " \n", 153 | " while node:\n", 154 | " print(node.data)\n", 155 | " node = node.next\n", 156 | " \n", 157 | " def search_from_head(self,data): # head 부터 검색\n", 158 | " node = self.head\n", 159 | " while node.next:\n", 160 | " if node.data == data:\n", 161 | " return node\n", 162 | " else:\n", 163 | " node = node.next\n", 164 | " \n", 165 | " return False\n", 166 | " \n", 167 | " def search_from_tail(self,data): # tail 부터 검색\n", 168 | " node = self.tail\n", 169 | " while node.prev:\n", 170 | " if node.data == data:\n", 171 | " return node\n", 172 | " else:\n", 173 | " node = node.prev\n", 174 | " \n", 175 | " return False\n", 176 | " \n", 177 | " def insert_before(self,data,before_data):\n", 178 | " if self.head is None:\n", 179 | " head = Node(data)\n", 180 | " else:\n", 181 | " node = self.tail\n", 182 | " while node.data != before_data:\n", 183 | " node = node.prev\n", 184 | " if node == None:\n", 185 | " return False\n", 186 | " new = Node(data)\n", 187 | " before_new = node.prev\n", 188 | " before_new.next = new\n", 189 | " new.prev = before_new\n", 190 | " new.next = node\n", 191 | " node.prev = new\n", 192 | " return True " 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 4, 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "name": "stdout", 202 | "output_type": "stream", 203 | "text": [ 204 | "0\n", 205 | "1\n", 206 | "2\n", 207 | "3\n", 208 | "4\n", 209 | "5\n", 210 | "6\n", 211 | "7\n", 212 | "8\n", 213 | "9\n" 214 | ] 215 | } 216 | ], 217 | "source": [ 218 | "double_linked_list = NodeMgmt(0)\n", 219 | "for data in range(1, 10):\n", 220 | " double_linked_list.insert(data)\n", 221 | " \n", 222 | "double_linked_list.print()" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": 5, 228 | "metadata": {}, 229 | "outputs": [ 230 | { 231 | "data": { 232 | "text/plain": [ 233 | "3" 234 | ] 235 | }, 236 | "execution_count": 5, 237 | "metadata": {}, 238 | "output_type": "execute_result" 239 | } 240 | ], 241 | "source": [ 242 | "double_linked_list.search_from_head(3).data" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": 6, 248 | "metadata": { 249 | "scrolled": true 250 | }, 251 | "outputs": [ 252 | { 253 | "data": { 254 | "text/plain": [ 255 | "6" 256 | ] 257 | }, 258 | "execution_count": 6, 259 | "metadata": {}, 260 | "output_type": "execute_result" 261 | } 262 | ], 263 | "source": [ 264 | "double_linked_list.search_from_tail(6).data" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": 7, 270 | "metadata": {}, 271 | "outputs": [ 272 | { 273 | "name": "stdout", 274 | "output_type": "stream", 275 | "text": [ 276 | "0\n", 277 | "1\n", 278 | "2\n", 279 | "3\n", 280 | "4\n", 281 | "5\n", 282 | "6\n", 283 | "7\n", 284 | "8\n", 285 | "9\n" 286 | ] 287 | } 288 | ], 289 | "source": [ 290 | "double_linked_list.print()" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 8, 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "data": { 300 | "text/plain": [ 301 | "True" 302 | ] 303 | }, 304 | "execution_count": 8, 305 | "metadata": {}, 306 | "output_type": "execute_result" 307 | } 308 | ], 309 | "source": [ 310 | "double_linked_list.insert_before(1.5,2)" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": 9, 316 | "metadata": { 317 | "scrolled": true 318 | }, 319 | "outputs": [ 320 | { 321 | "name": "stdout", 322 | "output_type": "stream", 323 | "text": [ 324 | "0\n", 325 | "1\n", 326 | "1.5\n", 327 | "2\n", 328 | "3\n", 329 | "4\n", 330 | "5\n", 331 | "6\n", 332 | "7\n", 333 | "8\n", 334 | "9\n" 335 | ] 336 | } 337 | ], 338 | "source": [ 339 | "double_linked_list.print()" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": {}, 345 | "source": [ 346 | "**연습4: 위 코드에서 노드 데이터가 특정 숫자인 노드 뒤에 데이터를 추가하는 함수를 만들고, 테스트해보기**\n", 347 | "- 더블 링크드 리스트의 head 에서부터 다음으로 이동하며, 특정 숫자인 노드를 찾는 방식으로 함수를 구현하기\n", 348 | "- 테스트: 임의로 0 ~ 9까지 데이터를 링크드 리스트에 넣어보고, 데이터 값이 1인 노드 다음에 1.7 데이터 값을 가진 노드를 추가해보기" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": 28, 354 | "metadata": {}, 355 | "outputs": [], 356 | "source": [ 357 | "class Node:\n", 358 | " def __init__(self,data,prev = None,next = None):\n", 359 | " self.data = data\n", 360 | " self.prev = None\n", 361 | " self.next = next\n", 362 | " \n", 363 | "class NodeMgmt:\n", 364 | " def __init__(self, data):\n", 365 | " self.head = Node(data)\n", 366 | " self.tail = Node(data)\n", 367 | " \n", 368 | " def insert(self, data):\n", 369 | " if self.head is None:\n", 370 | " self.head = Node(data)\n", 371 | " self.tail = Node(data)\n", 372 | " \n", 373 | " else:\n", 374 | " node = self.head\n", 375 | " while node.next: # 맨 마지막 노드 찾기\n", 376 | " node = node.next\n", 377 | " new = Node(data) \n", 378 | " node.next = new # 새로운 노드를 마지막 노드 다음으로 추가\n", 379 | " new.prev = node # 새로운 노드가 마지막 노드의 prev로 지정\n", 380 | " self.tail = new # tail update\n", 381 | " \n", 382 | " def print(self):\n", 383 | " node = self.head\n", 384 | " \n", 385 | " while node:\n", 386 | " print(node.data)\n", 387 | " node = node.next\n", 388 | " \n", 389 | " def search_from_head(self,data): # head 부터 검색\n", 390 | " node = self.head\n", 391 | " while node.next:\n", 392 | " if node.data == data:\n", 393 | " return node\n", 394 | " else:\n", 395 | " node = node.next\n", 396 | " \n", 397 | " return False\n", 398 | " \n", 399 | " def search_from_tail(self,data): # tail 부터 검색\n", 400 | " node = self.tail\n", 401 | " while node.prev:\n", 402 | " if node.data == data:\n", 403 | " return node\n", 404 | " else:\n", 405 | " node = node.prev\n", 406 | " \n", 407 | " return False\n", 408 | " \n", 409 | " def insert_after(self,data,after_data):\n", 410 | " if self.head is None:\n", 411 | " head = Node(data)\n", 412 | " else:\n", 413 | " node = self.head\n", 414 | " while node.data != after_data: # target node 찾기\n", 415 | " node = node.next\n", 416 | " if node is None:\n", 417 | " return False # 없으면 False 반환\n", 418 | " \n", 419 | " new = Node(data)\n", 420 | " tmp = node.next\n", 421 | " node.next = new\n", 422 | " new.prev = node\n", 423 | " new.next = tmp\n", 424 | " tmp.prev = new\n", 425 | " \n", 426 | " if new.next is None:\n", 427 | " self.tail = new\n", 428 | " \n", 429 | " return True" 430 | ] 431 | }, 432 | { 433 | "cell_type": "code", 434 | "execution_count": 29, 435 | "metadata": { 436 | "scrolled": true 437 | }, 438 | "outputs": [ 439 | { 440 | "name": "stdout", 441 | "output_type": "stream", 442 | "text": [ 443 | "0\n", 444 | "1\n", 445 | "2\n", 446 | "3\n", 447 | "4\n", 448 | "5\n", 449 | "6\n", 450 | "7\n", 451 | "8\n", 452 | "9\n", 453 | "----------------------------\n", 454 | "0\n", 455 | "1\n", 456 | "1.5\n", 457 | "2\n", 458 | "3\n", 459 | "4\n", 460 | "5\n", 461 | "6\n", 462 | "7\n", 463 | "8\n", 464 | "9\n" 465 | ] 466 | } 467 | ], 468 | "source": [ 469 | "node_mgmt = NodeMgmt(0)\n", 470 | "for data in range(1, 10):\n", 471 | " node_mgmt.insert(data)\n", 472 | "\n", 473 | "node_mgmt.print()\n", 474 | "print('----------------------------')\n", 475 | "node_mgmt.insert_after(1.5, 1)\n", 476 | "node_mgmt.print()" 477 | ] 478 | } 479 | ], 480 | "metadata": { 481 | "kernelspec": { 482 | "display_name": "Python 3", 483 | "language": "python", 484 | "name": "python3" 485 | }, 486 | "language_info": { 487 | "codemirror_mode": { 488 | "name": "ipython", 489 | "version": 3 490 | }, 491 | "file_extension": ".py", 492 | "mimetype": "text/x-python", 493 | "name": "python", 494 | "nbconvert_exporter": "python", 495 | "pygments_lexer": "ipython3", 496 | "version": "3.7.9" 497 | } 498 | }, 499 | "nbformat": 4, 500 | "nbformat_minor": 4 501 | } 502 | -------------------------------------------------------------------------------- /FastCampus/Data Structure/05-Time-Complexity.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 알고리즘 복잡도 표현 방법" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### 1. 알고리즘 복잡도 계산이 필요한 이유\n", 15 | "#### 하나의 문제를 푸는 알고리즘은 다양할 수 있음\n", 16 | " - 정수의 절대값 구하기\n", 17 | " - 1, -1 ->> 1\n", 18 | " - 방법1: 정수값을 제곱한 값에 다시 루트를 씌우기\n", 19 | " - 방법2: 정수가 음수인지 확인해서, 음수일 때만, -1을 곱하기\n", 20 | "\n", 21 | "> 다양한 알고리즘 중 어느 알고리즘이 더 좋은지를 분석하기 위해, 복잡도를 정의하고 계산함" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "### 2. 알고리즘 복잡도 계산 항목\n", 29 | "1. **시간 복잡도**: 알고리즘 실행 속도\n", 30 | "2. **공간 복잡도**: 알고리즘이 사용하는 메모리 사이즈\n", 31 | "\n", 32 | "> 가장 중요한 시간 복잡도를 꼭 이해하고 계산할 수 있어야 함" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "### 알고리즘 시간 복잡도의 주요 요소\n", 40 | "\n", 41 | "> 반복문이 지배합니다." 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "**생각해보기: 자동차로 서울에서 부산을 가기 위해, 다음과 같이 항목을 나누었을 때, 가장 총 시간에 영향을 많이 미칠 것 같은 요소는?**\n", 49 | "* 예: \n", 50 | " - 자동차로 서울에서 부산가기\n", 51 | " 1. 자동차 문열기\n", 52 | " 2. 자동차 문닫기\n", 53 | " 3. 자동차 운전석 등받이 조정하기\n", 54 | " 4. 자동차 시동걸기\n", 55 | " 5. 자동차로 서울에서 부산가기\n", 56 | " 6. 자동차 시동끄기\n", 57 | " 7. 자동차 문열기\n", 58 | " 8. 자동차 문닫기\n", 59 | "\n", 60 | "\n", 61 | "* 5번이 가장 시간이 많이 걸린다... (프로그래밍에서는 반복문이 이런 느낌)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "### 마찬가지로, 프로그래밍에서 시간 복잡도에 가장 영향을 많이 미치는 요소는 반복문\n", 69 | "* 입력의 크기가 커지면 커질수록 반복문이 알고리즘 수행 시간을 지배함" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "### 알고리즘 성능 표기법\n", 77 | "- Big O (빅-오) 표기법: O(N)\n", 78 | " - 알고리즘 최악의 실행 시간을 표기\n", 79 | " - **가장 많이/일반적으로 사용함**\n", 80 | " - **아무리 최악의 상황이라도, 이정도의 성능은 보장한다는 의미이기 때문**\n", 81 | "\n", 82 | "- Ω (오메가) 표기법: Ω(N)\n", 83 | " - 오메가 표기법은 알고리즘 최상의 실행 시간을 표기\n", 84 | "\n", 85 | "- Θ (세타) 표기법: Θ(N)\n", 86 | " - 오메가 표기법은 알고리즘 평균 실행 시간을 표기\n", 87 | "\n", 88 | "> 시간 복잡도 계산은 반복문이 핵심 요소임을 인지하고, 계산 표기는 최상, 평균, 최악 중, 최악의 시간인 Big-O 표기법을 중심으로 익히면 됨 " 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "### 3. 대문자 O 표기법\n", 96 | "* 빅 오 표기법, Big-O 표기법 이라고도 부름\n", 97 | "* O(입력)\n", 98 | " - 입력 n 에 따라 결정되는 시간 복잡도 함수\n", 99 | " - O(1), O($log n$), O(n), O(n$log n$), O($n^2$), O($2^n$), O(n!)등으로 표기함\n", 100 | " - 입력 n 의 크기에 따라 기하급수적으로 시간 복잡도가 늘어날 수 있음\n", 101 | " - O(1) < O($log n$) < O(n) < O(n$log n$) < O($n^2$) < O($2^n$) < O(n!)\n", 102 | " - 참고: log n 의 베이스는 2 - $log_2 n$\n", 103 | "\n", 104 | "* 단순하게 입력 n에 따라, 몇번 실행이 되는지를 계산하면 됩니다.\n", 105 | " - **표현식에 가장 큰 영향을 미치는 n 의 단위로 표기합니다.**\n", 106 | " - n이 1이든 100이든, 1000이든, 10000이든 실행을\n", 107 | " - 무조건 2회(상수회) 실행한다: O(1) \n", 108 | " ```python\n", 109 | " if n > 10:\n", 110 | " print(n)\n", 111 | " ```\n", 112 | " - n에 따라, n번, n + 10 번, 또는 3n + 10 번등 실행한다: O(n)\n", 113 | " ```python\n", 114 | " variable = 1\n", 115 | " for num in range(3):\n", 116 | " for index in range(n):\n", 117 | " print(index)\n", 118 | " ```\n", 119 | " - n에 따라, $n^2$번, $n^2$ + 1000 번, 100$n^2$ - 100, 또는 300$n^2$ + 1번등 실행한다: O($n^2$)\n", 120 | " ```python\n", 121 | " variable = 1\n", 122 | " for i in range(300):\n", 123 | " for num in range(n):\n", 124 | " for index in range(n):\n", 125 | " print(index)\n", 126 | " ``` " 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "* 빅 오 입력값 표기 방법\n", 141 | " - 예: \n", 142 | " - 만약 시간 복잡도 함수가 2$n^2$ + 3n 이라면\n", 143 | " - 가장 높은 차수는 2$n^2$ \n", 144 | " - 상수는 실제 큰 영향이 없음 \n", 145 | " - 결국 빅 오 표기법으로는 O($n^2$) (서울부터 부산까지 가는 자동차의 예를 상기)" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "### 4. 실제 알고리즘을 예로 각 알고리즘의 시간 복잡도와 빅 오 표기법 알아보기" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "**연습1: 1부터 n까지의 합을 구하는 알고리즘 작성해보기**" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "### 알고리즘1: 1부터 n까지의 합을 구하는 알고리즘1\n", 167 | "* 합을 기록할 변수를 만들고 0을 저장\n", 168 | "* n을 1부터 1씩 증가하면서 반복\n", 169 | "* 반복문 안에서 합을 기록할 변수에 1씩 증가된 값을 더함\n", 170 | "* 반복이 끝나면 합을 출력" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 1, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "def sum_all(n):\n", 180 | " total = 0\n", 181 | " for num in range(1, n + 1):\n", 182 | " total += num\n", 183 | " return total" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 2, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "data": { 193 | "text/plain": [ 194 | "5050" 195 | ] 196 | }, 197 | "execution_count": 2, 198 | "metadata": {}, 199 | "output_type": "execute_result" 200 | } 201 | ], 202 | "source": [ 203 | "sum_all(100)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "### 시간 복잡도 구하기\n", 211 | "* 1부터 n까지의 합을 구하는 알고리즘1\n", 212 | " - 입력 n에 따라 덧셈을 n 번 해야 함 (반복문!)\n", 213 | " - 시간 복잡도: n, 빅 오 표기법으로는 **O(n)**" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "### 알고리즘2: 1부터 n까지의 합을 구하는 알고리즘2\n", 221 | "* $\\frac { n (n + 1) }{ 2 }$" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 3, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "def sum_all(n):\n", 231 | " return int(n * (n + 1) / 2)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 4, 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "data": { 241 | "text/plain": [ 242 | "5050" 243 | ] 244 | }, 245 | "execution_count": 4, 246 | "metadata": {}, 247 | "output_type": "execute_result" 248 | } 249 | ], 250 | "source": [ 251 | "sum_all(100)" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "### 시간 복잡도 구하기\n", 259 | "* 1부터 n까지의 합을 구하는 알고리즘2\n", 260 | " - 입력 n이 어떻든 간에, 곱셈/덧셈/나눗셈 하면 됨 (반복문이 없음!)\n", 261 | " - 시간 복잡도: 1, 빅 오 표기법으로는 **O(1)**" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "### 어느 알고리즘이 성능이 좋은가요?\n", 269 | "- 알고리즘1 vs 알고리즘2\n", 270 | " - O(n) vs O(1)\n", 271 | "\n", 272 | "> 이와 같이, 동일한 문제를 푸는 알고리즘은 다양할 수 있음\n", 273 | "> 어느 알고리즘이 보다 좋은지를 객관적으로 비교하기 위해, 빅 오 표기법등의 시간복잡도 계산법을 사용함" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "#### 이후 자료구조, 알고리즘부터는 빅 오 표기법으로 성능을 계산해보면서, 빅 오 표기법과 계산방법에 익숙해지기로 합니다." 281 | ] 282 | } 283 | ], 284 | "metadata": { 285 | "kernelspec": { 286 | "display_name": "Python 3", 287 | "language": "python", 288 | "name": "python3" 289 | }, 290 | "language_info": { 291 | "codemirror_mode": { 292 | "name": "ipython", 293 | "version": 3 294 | }, 295 | "file_extension": ".py", 296 | "mimetype": "text/x-python", 297 | "name": "python", 298 | "nbconvert_exporter": "python", 299 | "pygments_lexer": "ipython3", 300 | "version": "3.7.9" 301 | } 302 | }, 303 | "nbformat": 4, 304 | "nbformat_minor": 4 305 | } 306 | -------------------------------------------------------------------------------- /FastCampus/Readme.md: -------------------------------------------------------------------------------- 1 | ## FastCampus 알고리즘 & 자료구조 2 | 3 | ### FastCampus 강의를 듣고 정리를 해보았습니다. 4 | 5 | #### 환경설정 6 | - 아나콘다를 이용하여 환경설정을 하였습니다. 7 | - `conda create --name fastCampus python=3.7` 8 | - `conda activate fastCampus` 9 | - `conda install jupyter` 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Algorithm-study 2 | 3 | #### 조금씩 꾸준하게 알고리즘 문제를 풀려고 노력중입니다. 4 | 5 | **`BOJ/`** - 직접 백준 문제를 풀고 풀면서 참고할 만한 사항들 `Readme.md`에 적어놓기 6 | **`FastCampus/`** - 자료구조 및 알고리즘 수업을 듣고 강의 노트 정리 7 | **`Softeer/`** - 직접 Softeer 문제를 풀고 풀면서 참고할 만한 사항들 `Readme.md`에 적어놓기 8 | 9 | -------------------------------------------------------------------------------- /Softeer/Readme.md: -------------------------------------------------------------------------------- 1 | ## Softeer 문제 풀면서 느낀 점 & 참고할 점 2 | 같은 유형의 알고리즘 문제를 풀 때, 조금 더 효율적으로 풀려고 메모를 해둔다. 3 | 4 | ### Lv 2 5 | 6 | #### [바이러스](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=407) 7 | - 제출 답안 : [virus.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/virus.cpp) 8 | - 처음에 큰 수를 다뤄야 해서 log를 이용해 보는 것으로 접근해봤지만 실패 9 | - 나머지를 다룰 때, 약간의 trick을 배울 수 있었다. 10 | - 두 곱의 나머지를 구할 때, 각각의 나머지를 구한 후 두 수를 곱하면 두 곱의 나머지를 쉽게 구할 수 있다. 11 | - 변수의 범위를 꼭 생각해주자. 12 | 13 | #### [지도 자동 구축](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=413) 14 | - 제출 답안 : [map_making.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/map_making.cpp) 15 | - 규칙을 찾는다면 쉽게 풀 수 있는 문제였다. 16 | - 여기서도 숫자의 범위를 주의해야 한다. 17 | 18 | #### [8단 변속기](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=408) 19 | - 제출 답안 : [transmission.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/transmission.cpp) 20 | - 단순하게 생각했는데, 정말 그 방법이 맞았던 문제 21 | - 일단 생각나는데로 코딩을 해보자. 22 | 23 | #### [금고 털이](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=395) 24 | - 제출 답안 : [safebreaker.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/safebreaker.cpp) 25 | - vector와 pair의 조합으로 Input을 받고, 내림차순을 이용하여 쉽게 풀 수 있었던 문제 26 | - 예외적인 경우를 항상 생각해보자. 27 | - 참고 : [vector> v; 정렬하는 방법](https://hsdevelopment.tistory.com/151) 28 | [[C++] pair와 vector 사용하기](https://m.blog.naver.com/PostView.nhn?blogId=ckdgus1433&logNo=221666899817&proxyReferer=https:%2F%2Fwww.google.com%2F) 29 | 30 | 31 | ### Lv 3 32 | 33 | #### [성적 평균](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=389) 34 | - 제출 답안 : [grade_average.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/grade_average.cpp) 35 | - 생각보다 시간이 너무 많이 걸렸다... 36 | - 처음에 incremental average를 이용하려 풀려고 했는데 실패... 37 | - 반올림을 일부러 해줬는데 통과하지 못했다. 38 | - 부분합을 이용하여 배열에 저장하면 쉽게 풀 수 있다. 39 | - static cast 쓰는 법도 알아두자. 40 | - 출처 : [[C++] static_cast (타입캐스트 연산자)](https://blockdmask.tistory.com/236) 41 | 42 | #### [스마트 물류](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=414) 43 | - 제출 답안 : [smart_logistics.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/smart_logistics.cpp) 44 | - 플래그(bool 배열)를 이용하여 풀 수 있었던 문제 45 | - 로봇이 집을 수 있는 최대한 멀리 있는 것을 집고, 왼쪽부터 순서대로 집는다는 가정을 했는데 그 가정이 맞았던 것 같다. 46 | 47 | #### [징검다리](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=390) 48 | - 제출 답안 : [stepping_stone.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/stepping_stone.cpp) 49 | - 큐 자료구조를 이용해서 풀려고 했으나, 실패... 예외처리를 실패한 것 같다. 50 | - Algo tutor를 보고 힌트를 얻어 문제를 풀었다. 51 | - 전역 변수로 배열을 만들어서 푸는 것이 가장 일반적인 듯 52 | 53 | #### [우물 안 개구리](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=394) 54 | - 제출 답안 : [frog_in_the_well.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/frog_in_the_well.cpp) 55 | - 처음에 문제를 잘못 읽어서 헤멘 문제... 56 | - 만약 비교를 하지 않으면 내가 세다고 계속 인식한다는 것을 놓침. 57 | - 그 이외에는 내가 생각했던 것처럼 풀면 풀 수 있었던 문제 58 | 59 | 60 | #### [강의실 배정](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=392) 61 | - 제출 답안 : [classroom_assignment.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/classroom_assignment.cpp) 62 | - 시간초과가 떠서 처음에 통과를 못했던 문제... 63 | - 시간도 항상 check를 하면서 문제를 풀자! 64 | - 정렬을 해야한다는 것은 맞았지만, 어떤 것을 정렬해야 하는지 틀렸던 문제 65 | - Algo tutor를 보고 힌트를 얻어 문제를 풀었다. 66 | - 강의실 배정 : 강의를 최대한 많이 배정하는 문제인지, 강의실의 활용률을 최대한으로 하는 것인지 구분하자! 67 | 68 | #### [조립 라인](https://softeer.ai/practice/info.do?eventIdx=1&psProblemId=403) 69 | - 제출 답안 : [assembly_line.cpp](https://github.com/Taeyoung96/Algorithm-study/blob/main/Softeer/assembly_line.cpp) 70 | - Algo tutor를 보고 힌트를 얻어 풀 수 있었던 문제 71 | - 부분합을 이용하면 시간 복잡도를 확 줄일 수 있다. 72 | -------------------------------------------------------------------------------- /Softeer/assembly_line.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/assembly_line.cpp -------------------------------------------------------------------------------- /Softeer/classroom_assignment.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/classroom_assignment.cpp -------------------------------------------------------------------------------- /Softeer/frog_in_the_well.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/frog_in_the_well.cpp -------------------------------------------------------------------------------- /Softeer/grade_average.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | long long arr[1000001] = { 0, }; 9 | long long score_sum[1000001] = {0,}; 10 | 11 | int main(int argc, char** argv) 12 | { 13 | ios::sync_with_stdio(false); 14 | cin.tie(NULL); 15 | cout.tie(NULL); 16 | cout.precision(2); 17 | cout << fixed; 18 | 19 | long long n, k, sum = 0.; 20 | 21 | cin >> n; 22 | cin >> k; 23 | 24 | for (long long i = 1; i <= n; i++) { 25 | 26 | int score = 0; 27 | cin >> score; 28 | arr[i] = score; 29 | score_sum[i] = arr[i] + score_sum[i-1]; 30 | } 31 | 32 | for (long long j = 0; j < k; j++){ 33 | long long start, end; 34 | cin >> start; 35 | cin >> end; 36 | 37 | long long num = end - start + 1; 38 | long long startIdx = start - 1; 39 | long long endIdx = end; 40 | long long startSum, endSum; 41 | 42 | 43 | startSum = score_sum[startIdx]; 44 | endSum = score_sum[endIdx]; 45 | 46 | double avg = static_cast(endSum - startSum) / static_cast(num); 47 | 48 | cout << avg << "\n"; 49 | 50 | } 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /Softeer/map_making.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(int argc, char** argv) 6 | { 7 | unsigned long long n; 8 | unsigned long long a = 2; 9 | unsigned long long result = 1; 10 | unsigned long long result2; 11 | 12 | cin >> n; 13 | 14 | for (int i = 0; i < n; i++){ 15 | result = a * result; 16 | } 17 | 18 | result = result + 1; 19 | result2 = result * result; 20 | 21 | cout << result2 << "\n"; 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /Softeer/safebreaker.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/safebreaker.cpp -------------------------------------------------------------------------------- /Softeer/smart_logistics.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/smart_logistics.cpp -------------------------------------------------------------------------------- /Softeer/stepping_stone.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Taeyoung96/Algorithm-study/6b8189eb4aa308860db48ddd20d7de50627cfa70/Softeer/stepping_stone.cpp -------------------------------------------------------------------------------- /Softeer/transmission.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main(int argc, char** argv) 7 | { 8 | vector input; 9 | for(int i = 0; i <8;i++){ 10 | int num = 0; 11 | cin >> num; 12 | input.push_back(num); 13 | } 14 | 15 | if((input[0]==1)&&(input[1]==2)&&(input[2]==3)&&(input[3]==4)&& 16 | (input[4]==5)&&(input[5]==6)&&(input[6]==7)&&(input[7]==8)){ 17 | cout << "ascending" << endl; 18 | } 19 | else if((input[0]==8)&&(input[1]==7)&&(input[2]==6)&&(input[3]==5)&& 20 | (input[4]==4)&&(input[5]==3)&&(input[6]==2)&&(input[7]==1)){ 21 | cout << "descending" << endl; 22 | } 23 | else { 24 | cout << "mixed" << endl; 25 | } 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /Softeer/virus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main(int argc, char** argv) 7 | { 8 | int k, p, n, target = 1000000007; 9 | int answer; 10 | cin >> k; 11 | cin >> p; 12 | cin >> n; 13 | 14 | for (int i = 0; i < n; i++) { 15 | if (i == 0) { 16 | answer = k * p; 17 | } 18 | else { 19 | answer = answer * p; 20 | } 21 | answer = answer % target; 22 | } 23 | 24 | answer = answer % target; 25 | 26 | cout << answer << endl; 27 | 28 | return 0; 29 | } --------------------------------------------------------------------------------