일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- mysql # SQL # 프로그래머스 # 코딩테스트
- 프로그래머스 # 코딩테스트 # SQL # mysql # 차집합
- inflearn
- NVIDIA # GTC 2020 # Webinar # GTC 행사
- 딥러닝 # GPU # 프레임워크 # 엣지 AI # GTC 2020 Online
- 딥러닝#초보#MLE#Cross-entropy#메모
- Git
- 프로그래머스 # sql # mysql # 코딩테스트 # 연습
- udacity#유다시티#자료구조#알고리즘#기초
- 파이썬 # python # copy
- github
- 프로그래머스 # sql #mysql # 코딩테스트 # recursive cte
- spark#apache spark#입문#스파크#빅데이터
- Today
- Total
from Karte,
[Udacity] Intro to Data Structures and Algorithms : Lesson #1. Introduction and Efficiency 본문
[Udacity] Intro to Data Structures and Algorithms : Lesson #1. Introduction and Efficiency
karte 2020. 11. 17. 14:38*Udacity 의 Intro to Data Structures and Algorithms 강의 (무료) 를 수강하며 배운 내용을 정리할 목적으로 작성하는 글로, 그 어떤 금전적 지원도 받은 사실이 없음을 밝힙니다.
*영어로 제공되는 강의를 듣고 한국어로 내용 정리를하는 포스팅이기에 강의의 내용을 100% 포함하고 있지 않을 수 있다는 점 참고 바랍니다. 원본 내용이 확인하고 싶으신 분들은 Udacity 에 회원가입 후 해당 강의를 수강 신청하시길 바랍니다.
*포스팅 내용에 오류가 있을 시 댓글로 남겨주세요! 바로 수정하겠습니다.
드디어 찾았다. 내 맘에 쏙 드는 강의. 이전부터 자료구조와 알고리즘을 듣고 싶었으나 대부분 자바같이 내가 잘 모르는 언어들로 과제가 나와서 미루고 있다가 최근 Udacity 에서 파이썬으로 진행되는 강의를 찾게 되었다. 심지어 무료다!
곧 코드가 필요없어지는 시대가 올 텐데 뭐하러 귀찮고 힘든 길을 가냐는 의견이 있을 수 있지만, 개인적으로는 무대 뒤에서 어떤 일들이 진행되고 있는지 아는 것이 중요하다고 생각해서 망설임 없이 배우기로 했다.
총 8강으로 구성된 과목의 1강을 듣고 있는 중인데, 앞으로 공부한 내용을 필요하다면 언제든지 찾아볼 수 있도록 블로그에 기록하려고 한다.
1. 효율성 Efficiency 또는 복잡도 Complexity
CS 에서 '효율성' 이란 개념은 곧 어떤 코드 (혹은 프로그램) 가 실행 완료되기까지 얼만큼의 시간이 걸리는지, 어느 정도의 저장 공간 (space storage) 을 차지하는지를 말한다. 즉, 코드가 실행될 때 컴퓨터의 리소스를 얼마나 차지하는지를 의미한다. 당연히 같은 작업을 실행하는 코드라면 리소스를 최소로 사용하는 코드가 더 좋은 코드다.
그러나 모든 경우에 있어 실행 시간도 적게 걸리고, 메모리도 적게 사용하는 코드를 짜는 것은 어려운 일이다. 그러므로 종종 실행 시간과 메모리 사이에서 어떤 것을 더 우위에 둘지 선택 (trade-offs) 을 해야할 수도 있다.
* 사족: 이 설명을 듣고 자료 구조와 알고리즘을 왜 배워야 하는지 이해할 수 있었다. 데이터를 어떤 그릇에 담아서 (자료구조) 어떤 방식으로(알고리즘) 처리를 하는 것이 가장 문제에 맞는 것인지 배울 수 있는 과목이기 때문이다. 다른 말로 표현하면, 효율적인 코드를 짜는 것이 '목표 goal' 라면 그 목표를 달성할 수 있게 해주는 '방법 how' 를 알려주는 과목이기 때문에 배워야 하는 것이다.
- 표기법 (Notation) 기초 : O(n)
Big O notaion 이라고 읽으면 된다. 알고리즘의 효율성을 정량적 - 사실 대수적이라는 표현이 더 맞는지 아니면 그냥 객관적이라는 표현을 써야하는지 잘 모르겠다 - 으로 측정할 수 있는 방법이다.
O(n) 에서 n 은 대수적 표현들이다. 예를 들면 O(1), O(log(n)), O(n^2) 이런 식이다. 이때 O(1) 이 왜 예시에 포함되어 있는지 궁금할 수 있는데, 1 = 0*n + 1 로 표현할 수 있기 때문이다.
n 이 어떤 식으로 표기되는지는 알겠는데, 의미하는 바는 무엇일까? 바로 입력되는 데이터의 길이이다.
이제 아래의 예를 통해 시간 복잡도 time efficiency 를 이해해 보자.
암호를 문자열의 형태로 입력받아 미리 정의한 암호표와 비교한 후 해당 암호가 어떤 의미인지 알려주는 함수를 정의한 의사 코드 pseudo code 이다. (글자색과 들여쓰기는 무시하고 읽길 바란다.)
function decode(input):
create output string
for each letter in input: #한 글자씩 해독
get new_letter from letter's location in cipher #암호표는 cipher 라는 이름으로 저장되어 있음
add new_letter to output #해독 완료한 글자를 output 에 순차적으로 포함시키기
return output
함수가 1번 실행될 때 create output string 과 return output 은 각각 1번씩만 실행되는 코드이다. 따라서, 이점을 반영하여 O( ___ + 2) 라고 (이유: create 으로 시작하는 코드 1줄 + return 으로 시작하는 코드 1줄) 우선 쓸 수 있다. 다음으로, 입력받은 문자열에 n 개의 글자가 있다고 할 때, 함수 1번 실행 시 for 문 안에 있는 코드 2줄은 더 읽을 글자가 없을 때까지 계속 실행된다. 따라서 O(2*n + 2) 라고 쓸 수 있다. (이유: 글자 n 개 * 글자 1개 당 코드 2줄)
시간 복잡도를 구하면, O(2*n + 2) 에 코드의 1회 실행 시간이다. 예를 들어 위 함수가 1번 실행되는데 1초가 걸리고, 입력받은 문자열이 10개의 글자로 이루어져 있다면 시간 복잡도는 22 계산 횟수 *1초 = 22초가 된다. (이유: 글자가 10개이므로 O(2*n + 2) 의 n 에 10 대입)
- 표기법 (Notation) 계속
바로 윗 단락까지가 기초 중의 기초에 해당하는 내용이었는데, 사실 O(n) 을 잘못 썼다. 왜냐하면, for 문을 빼먹었기 때문이다. for 문이 입력받은 문자열에서 글자를 1개씩 가져올 때, 바로 다음에 어떤 글자를 가져올지에 대한 계산이 이루어지므로 O((2+1)*n + 2) = O(3*n + 2) 으로 쓰는 것이 맞다.
여기서 안심해도 될까? 아니다. 암호문을 저장한 cipher 가 남아있다...! 예를 들어 해독을 하려는 문자열이 영어 알파벳이라고 생각할 때 cipher 에는 26개의 알파벳이 어떤 암호 표시에 대응하는지에 대한 정보를 담고 있을 것이다. 그럼 함수가 1번 실행될 때, for 문 바로 아래의 get new_letter from letter's location in cipher 코드는 최대 26번의 대조 작업을 할 수도 있는 것이다. 이 경우 O(n) 은 O((3+26)*n + 2) = O(29*n + 2) 이 된다. 10개 글자로 이루어진 암호 문자열을 입력했을 때 시간 복잡도를 계산하면 292초가 된다. (함수 실행 완료까지 걸리는 시간은 1초로 동일)
- 최악의 경우와 근사법 Worst Case and Approximation
<표기법 (Notation) 계속> 에서 확인한 것처럼, O(3*n + 2) 라는 복잡도 표현식은 상황에 따라 달라질 수 있다. 따라서 보통의 경우, 예를 들어 개발자 코딩 면접에서는 계수나 상수까지 구체적으로 포함한 복잡도를 구할 수 있는지 묻지 않고, 대신 근사식으로 표현할 수 있는지를 확인한다고 한다. 이를테면 O(29*n + 2) 대신 O(n) 라고 쓰는 것이다.
사실 코드의 효율성(복잡도)에 대해 언급할 수 있는 방법에는 3가지가 있는데, 첫번째는 Best Case 를 가정하는 경우고 두번째는 Average Case 를 가정하는 경우, 그리고 마지막으로는 Worst Case 를 가정하는 경우이다. O(29*n + 2) 는 최악의 경우, 즉 암호 문자열 내의 글자를 cipher 의 알파벳과 26번 대조하게 되는 상황을 가정하고 도출한 값이다. 만약 평균적인 경우를 가정한다면, 보통 13번의 대조를 통해 대응되는 알파벳이 무엇인지 알게 될 것이므로 O(16*n + 2) 를 복잡도라고 할 것이다.
수업에서는 시간 복잡도를 주로 다루었는데, '공간 복잡도' 라는 개념도 존재한다. 예를 들어, 문자열을 입력받아 3번 복사하는 작업을 한다고 할 때, 공간 복잡도는 O(3*n) 과 같이 표현된다.
이상 1강에서 배운 효율성(복잡도)의 정리를 마친다! 과연 언제 완강을 할 수 있을지 기대된다. (두근)
'study log > Python' 카테고리의 다른 글
파이썬에서의 deepcopy 와 shallow copy feat. copy module (0) | 2020.10.04 |
---|