파이썬 크롤링 (beautifulsoup, selenium 활용)

|

패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

Scraping vs Crawling vs Parsing

  • 추천도서
  • 스크랩핑(scraping) : 데이터를 수집하는 행위
  • 크롤링(Crawling) : 조직적 자동화된 방법으로 월드와이드웹을 탐색 하는 것
  • 파싱(parsing) : 문장 혹은 문서를 구성 성분으로 분해하고 위계관계를 분석하여 문장의 구조를 결정하는 것

beautifulsoup을 사용한 스크랩핑 1

beautifulsoup

  • 공식문서
  • BeautifulSoup 모듈은 HTML과 XML을 파싱하는 데에 사용되는 파이썬 라이브러리
  • 설치
$ pip install beautifulsoup4
$ pip list
  • 목표 :https://www.rottentomatoes.com 사이트 메인화면의 Top Box Office에 해당하는 영화 제목과 링크 리스트를 가져온다.
from urllib.request import urlopen
from bs4 import BeautifulSoup


url = "https://www.rottentomatoes.com/"
html = urlopen(url)
source = html.read() # 바이트코드 type으로 소스를 읽는다.
html.close() # urlopen을 진행한 후에는 close를 한다.

soup = BeautifulSoup(source, "html5lib") # 파싱할 문서를 BeautifulSoup 클래스의 생성자에 넘겨주어 문서 개체를 생성, 관습적으로 soup 이라 부름
table = soup.find(id="Top-Box-Office")
movies = table.find_all(class_="middle_col")

for movie in movies:
    title = movie.get_text()
    print(title, end=' ')
    link = movie.a.get('href')
    url = 'https://www.rottentomatoes.com' + link
    print(url)
  • 결과화면
The Fate of the Furious
https://www.rottentomatoes.com/m/the_fate_of_the_furious

The Boss Baby
https://www.rottentomatoes.com/m/the_boss_baby

Beauty and the Beast
https://www.rottentomatoes.com/m/beauty_and_the_beast_2017

....
....

beautifulsoup을 사용한 스크랩핑 2

  • 목표 : stack overflow 에서 python 검색 결과 질문 리스트와 링크를 가져온다.
from urllib.request import urlopen
from bs4 import BeautifulSoup

page = urlopen("http://stackoverflow.com/questions/tagged/python")
document = page.read()
page.close()

soup = BeautifulSoup(document, 'html5lib')

questions = soup.find(id="questions")
questions_list = questions.find_all("a", class_="question-hyperlink")

for question in questions_list:
    print(question.get_text())
    print('http://stackoverflow.com' + question.get('href'))
  • 결과화면
Mutually exclusive many-to-many relationship in Django models
http://stackoverflow.com/questions/43657599/mutually-exclusive-many-to-many-relationship-in-django-models
How can I get the index of selected item in a treeview?
http://stackoverflow.com/questions/43657591/how-can-i-get-the-index-of-selected-item-in-a-treeview
How to install Tkinter module with python 2.7.5 in Redhat linux 7?
http://stackoverflow.com/questions/43657590/how-to-install-tkinter-module-with-python-2-7-5-in-redhat-linux-7
Grouping columns in python tabulate alphabetically
http://stackoverflow.com/questions/43657584/grouping-columns-in-python-tabulate-alphabetically
...
...

selenium을 사용한 크롤링(Crawling)

  • beautifulsoup은 사용자 행동을 특정해서 데이터를 가져올 수 없다.
  • 사용자의 행동을 동적으로 추가하려면 selenium이 필요하다.

selenium 및 웹 드라이버 설치

  • selenium 설치
  • Selenium은 테스트 코드 실행으로 브라우저에서의 액션을 테스트 할 수 있게 해주는 테스팅 도구
$ pip install selenium
  • geckodriver 설치
  • geckodriver 다운로드 후 압축을 풀고, usr/local/bin 경로에 옮긴다.
  • 드라이버는 브라우저를 띄우고 통제 드라이빙하는 역할을 한다. (WebDriver는 웹 브라우저와 selenium API 사이의 교량 역할을 한다. 테스트될 웹 페이지에 jQuery가 로드되어 있으면 selenium API를 통해서도 그와 관련된 이벤트를 전송할 수 있다. 테스트될 웹 페이지에 특정 css가 로드되어 있으면 이 또한 참조할 수 있다. URL 변경, input 테그의 내용 조작, css 변경 등 해당 웹 페이지의 모든 것을 제어할 수 있다.)
$ sudo mv geckodriver /usr/local/bin

selenium을 사용한 google 크롤링

  • 목표 : 구글에 접속하여 ‘macbook pro’를 검색하고, 검색 결과 제목을 가져온다.
  • 코드
import os
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

ff_driver = webdriver.Firefox()
ff_driver.get("https://www.google.co.kr")

query = ff_driver.find_element_by_id("lst-ib").send_keys("macbook pro")
ff_driver.find_element_by_name("btnK").click()

WebDriverWait(ff_driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "h3.r")))

page_results = ff_driver.find_elements(By.CSS_SELECTOR, "h3.r")

for item in page_results:
    print(item.text)
  • 결과화면
MacBook Pro - Apple (KR)
MacBook Pro 구입하기 - Apple (KR)
MacBook Pro 식별 방법 - Apple 지원
Apple MacBook Pro - Best Buy
MacBook Pro - Wikipedia
MacBook Pro: Thinner Design With New OLED Touch Bar, Order Now
Vertical MacBook Pro 2016 – Henge Docks
New MacBook Pro - iStore
Apple MacBooks: Pro, Air, Original Macbook | B&H
Amazon.com: Apple MacBook Pro MF839LL/A 13.3-Inch Laptop with ...

Reference

jupyter notebook 배경화면 색 변경하기

|

python수업을 듣거나 알고리즘 문제를 풀 때 jupyter notebook을 자주 사용하고 있다. 코드를 수정하기 편하고 결과를 바로 확인 할 수 있어서 좋은데, 배경화면이 흰색이라 눈이 아팠다. 레티나에서 볼 때는 봐줄만 하지만 외부모니터(DELL Ultrasharp)는 눈이 부셔서 흰 화면을 띄우기가 힘들다.

그래서 찾아보니 간단하게 iPython Jupyter Notebook 테마를 바꿀수 있었다!

jupyter notebook 배경화면 색 변경하는 방법

css 수정

  • custom.css 파일을 만들고 원하는 테마의 CSS 코드를 입력한다.
  • custom.css 파일의 경로는 아래와 같다. 나는 atom으로 파일을 편집했다.
# css 파일 편집하기
$ atom ~/.jupyter/custom/custom.css

테마 종류

views
변경 전
views
변경 후

(참고) 사라진 toolbar 되돌리기

  • 테마색을 바꾸고 만족스럽게 사용하고 있었는데, 상단의 toolbar가 사라져 있는걸 발견했다. 가이드 문서를 보니 테마 개발자가 쓸모가 없다고 생각해서 숨김처리 (display: none) 했다고 한다.
  • toolbar를 원래 상태로 되돌리려면 css 내용 중에서 아래 부분을 삭제하면 된다.
div#maintoolbar, div#header {display: none !important;}

codility - BinaryGap (시간복잡도 평가 추가)

|

문제출처

문제

A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N.

For example, number 9 has binary representation 1001 and contains a binary gap of length 2. The number 529 has binary representation 1000010001 and contains two binary gaps: one of length 4 and one of length 3. The number 20 has binary representation 10100 and contains one binary gap of length 1. The number 15 has binary representation 1111 and has no binary gaps.

Write a function:

def solution(N)

**that, given a positive integer N, returns the length of its longest binary gap. The function should return 0 if N doesn’t contain a binary gap.

For example, given N = 1041 the function should return 5, because N has binary representation 10000010001 and so its longest binary gap is of length 5.**

Assume that:

N is an integer within the range [1..2,147,483,647].

Complexity:

**expected worst-case time complexity is O(log(N));

expected worst-case space complexity is O(1).**

풀이과정

  • 함수의 인자로 받은 N을 2진수로 바꾼다
  • 2진수 N의 각 자릿수 중에 1에 해당하는 자릿수의 인덱스 값을 찾아 빈 배열에 담는다.
  • 배열에 담긴 요소를 인접한 요소와 뺀 결과를 새로운 빈 배열에 담는다.
  • 그중에서 최댓값을 리턴한다.

풀이코드

def solution(N):
    N = bin(N)[2:] # 함수의 인자로 받은 N을 2진수로 바꾼다, format(N, 'b') 도 가능
    arr = []

    for idx, value in enumerate(N):
        if value == '1':
            arr.append(idx) # 2진수 N의 각 자릿수 중에 1에 해당하는 자릿수의 인덱스 값을 찾아 빈 배열에 담는다.

    arr2 = []    

    for i in range(len(arr)-1):
        arr2.append(arr[i+1] - arr[i] - 1) # 배열에 담긴 요소를 인접한 요소와 뺀 결과를 새로운 빈 배열에 담는다.

    return max(arr2) # 그 중에서 최댓값을 리턴한다.

Big-O

  • (1) ~ (9)를 더하면 5N + 4 Big-O 로 표현하면 O(N)
def solution(N):
    N = bin(N)[2:] # (1) Big-O : constant 1
    arr = [] # (2) Big-O: constant 1

    for idx, value in enumerate(N): # (3) Big-O: N
        if value == '1': # (4) Big-O: N
            arr.append(idx) # (5) Big-O: N

    arr2 = [] # (6) Big-O: constant 1    

    for i in range(len(arr)-1): # (7) Big-O : N
        arr2.append(arr[i+1] - arr[i] - 1) # (8) Big-O: N

    return max(arr2) # (9) Big-O: constant 1

다른 사람 코드

  • Big-O : O(N)
#1
def solution(N):
  return len(max(bin(N)[2:].strip('0').strip('1').split('1'))) # Big-O : N

#2
def solution(N):
  return len(max(format(N, 'b').strip('0').split('1'))) # Big-O : N  

.strip() / .split()

  • str.strip() 메소드를 활용하여 문자열 양 끝에서 원하는 연속된 문자열을 삭제할 수 있다.
# 2진수 '100100010000' 의 경우,

'100100010000'.strip('0')
# '10010001'
# 좌, 우 끝의 모든 연속된 0을 삭제

'100100010000'.strip('0').strip('1')
# '001000'
# 좌,우 끝의 모든 연속된 1을 삭제

'100100010000'.strip('0').strip('1').split('1')
# ['00', '000']
# 1을 기준으로 문자열을 나눠 배열에 담는다

시간 복잡도 측정 (time complexity)

  • 참고자료-추천, 참고자료,
  • Big O 표기법은 컴퓨터 공학에서 알고리즘의 복잡도 또는 성능을 표현하기 위해 사용된다. Big O는 특히 최악의 경우를 표현하며, 특정 알고리즘을 수행하는데 특정 시간안에 수행된다는 것을 보장한다는 의미를 가진다.
  • Bio 표기법 종류 (상세 내용은 자료 참고)
    • O(1), O(N), O(N^2), O(2^N), O(log N), O(N log N)
    • 이진 탐색 같은 알고리즘은 O(log N)의 성능을 가지며 대용량의 데이터를 처리하는데 아주 효율적이다.
  • 알고리즘의 계산복잡도를 결정하는 요소는 크게 네 가지로 구분할 수 있다.
    • 단순 반복문(루프)
    • 재귀호출
    • 테스트 문(IF, WHILE, 또는 UNTIL)
    • 함수의 호출
  • 반복문의 계산복잡도는 반복되는 횟수를 통해 쉽게 구할 수 있고, 입력값의 수에 대해 항상 일정하고, 입력되는 값에 좌우되지 않는다. (각 명령이 끝날 때마다 실행 횟수를 적고 더한 후, 상수는 생략하고 최고차항만 고려한다.)
  • 반면에 재귀호출이나 테스트 문의 경우에는 새로운 문제를 야기시키는데, 입력되는 값이 따라 계산 복잡도가 바뀌는 것이다. 일반적으로 세 가지 경우를 생각한다. Best Case, Average Case, Worst Case가 그것이다.

170424-0430_TIL

|

4월 30일 (일)

오늘 한 일 (회고)

내일 할 일

4월 29일 (토)

오늘 할 일(계획)

  • 파이썬 웹프로그래밍 책 읽고 실습 - 설계에 주의 하면서 연습할 것 (스터디 적용방법 함께 고민)

오늘 한 일 (회고)

  • 파이썬 웹프로그래밍](http://www.yes24.com/24/goods/17295239?scode=032&OzSrank=1) 책을 읽고 간단한 투표 어플리케이션을 만들었다.
    • 글로 정리되어 있어서 그런지 동영상 강의 보다 좀 더 체계적이고 구체적이라는 인상을 받았다. (괜찮은 것 같다!)
    • 책에 장고를 활용한 개발 순서에 대한 부분이 도움이 되었다. (이 부분은 앞으로 참고하고 싶어서 따로 정리해두었다.)
    • 결국 django 공식문서 가 가장 좋은 교제라는 의견이 가장 많은 것 같다.
  • 새롭게 django 프로젝트를 생성할 때 마다 개발환경을 설정하는 부분을 반복해서 찾아봤었다. 블로그에 올려 놓은 글도 흩어져 있어서 이번 기회에 다시 정리하였다. 매번 찾아보는 python 개발환경 세팅 (pyenv, virtualenv, autoenv) + django 프로젝트 및 앱 생성하기

내일 할 일

  • 스터디 준비 (Big-O 부분 예습하기) 및 스터디 참여
  • 책에서 읽은 장고 개발 절차를 미니 프로젝트에 어떻게 적용할지 생각해보기
  • 파이썬 웹프로그래밍 chapter4 읽기

4월 28일 (금)

5/8 개강하는 웹프로그래밍 스쿨이 11일 남았다. 남은 시간 동안 무엇을 공부하며 어떻게 보내는게 좋을까? (우선순위)

  • django 공식문서 읽고 연습 - 영어문서에 익숙해 질 것!
  • AskDjango 수업
  • 자료구조 알고리즘 공부 (스터디)
  • 파이썬 웹프로그래밍 책 읽으며 실습
  • 생활코딩 github (gui) 강의듣고 sourcetree를 사용한 git 활용법 익히기

오늘 할 일 (계획)

오늘 한 일 (회고)

  • 여행 블로그 연습 프로젝트 진행
    • 동작 단위별로 커밋하기에 신경쓰면서 연습을 진행하였다. (확실히 다시 보기에 편한 것 같다! 앞으로 모든 연습 프로젝트의 커밋을 더 신경써야겠다는 생각을 했다.)
    • google map 적용과 댓글 추가, 수정, 삭제 기능을 구현하였다.
  • git flow에 관련된 글을 읽고 테스트를 위한 collaborator 계정과 repository를 만들어 연습해보았다. github 웹후크를 등록하고 slack을 사용하여 변경사항 알람을 받도록 설정했다.

4월 27일 (목)

오늘 할 일 (계획)

  • 컴퓨터 공학 수업 참여 (마지막 수업!)
  • 스크랩핑, 크롤링 수업내용 정리
  • vagrant 설치하고 가상환경 위에 postgreSQL 설치

오늘 한 일

  • 컴퓨터 공학 마지막 수업에 참여하였다.
    • 플래닝 포커 를 통해서 주어진 문제를 푸는데 어느정도의 시간이 걸릴지 협의하고, 2명씩 팀을 이루어 페어 프로그래밍 을 진행하였다.
    • 전략을 제시하는 네비게이터와 코드를 작성하는 드라이버의 역할을 5분에 한번씩 돌아가면서 맡았는데 신선하고 즐거운 경험이었다. 비록 3문제 중에 1문제 밖에 풀지 못했지만 생각했던 풀이 방식에 대해서 상대방에게 말로 설명하면서 막연했던 생각이 더 구체화 되는 기분도 들었다.
    • 배려심 있는 좋은 팀원을 만나 즐겁게 진행했는데, 그렇지 않은 팀도 있었나보다 (‘잘하면 고효율, 못하면 가문의 원수가 되는 짝프로그래밍’ 이라는 말이 그냥 나온 말이 아닌가 보다..)
    • 실력도 중요하지만 무엇보다 함께 일하고 싶은 사람 이 되어야겠다는 생각을 다시 했다.
    • 한달 동안 거의 매일같이 수업에 참여했는데, 수업 이전에 3달 정도를 혼자 공부하다가 다른 사람들과 함께 공부하니 즐거웠다. 특히 바로 궁금한 걸 물어볼 수 있는 선생님이 계시는 게 좋았다.
  • 스크랩핑, 크롤링 수업 내용을 다시 연습하고 강의노트를 정리했다. 아직 구체적으로 필요성을 느끼지 못해서 그런지 적극적으로 찾아서 배우고 싶다는 마음은 (아직은) 생기지 않는다. 그리고 무엇보다 만들고 싶은걸 하려면 공부해야 할 것들이 많다..!
  • django 연습 프로젝트의 github의 커밋 이력을 다시 읽어보았다. 그동안은 별다른 기준 없이 커밋을 진행했지만, 이제부터는 선생님의 패턴을 참고하여 신경써서 진행하려고 한다. 복습겸 깃헙에서 커밋 이력을 살펴보았는데, 작은 단위로 커밋을 진행하니 훨씬 코드를 수정사항을 이해하기 빠르다는 인상을 받았다.

내일 할 일

  • codility 알고리즘 문제 풀기
  • django 공부하기! (AskDjango)

4월 26일 (수)

오늘 할 일 (계획)

오늘 한 일 (회고)

  • Flask, sqlite를 사용하여 db를 화면에 표시하고, form을 사용하여 post로 전송한 데이터를 db에 저장하는 기능을 연습했다. django에서 구현해본 기능이라 공식문서를 찾아보면 쉽게 구현할 수 있지 않을까 생각했는데 생각보다 시간이 걸렸다. 그동안 한국어로 된 동영상 강의를 보면서 너무 쉽게만 배운려고 한건 아니었나 생각이 들었다. 앞으로 일부러라도 공식 기술 문서를 읽고 원하는 기능을 구현하는 경험을 쌓아야겠다.

내일 할 일

  • vagrant 설치하고 가상환경 위에 postgreSQL 설치
  • django 프로젝트 내 app 구분 기준에 대해서 선생님께 의견 들어보기
  • 컴퓨터 공학 입문 마지막 수업 참여

4월 25일 (화)

오늘 할 일 (계획)

  • BinaryGap 알고리즘 문제 다른사람 풀이 살펴보기
  • Big-O 에 대해서 공부하고 알고리즘 문제 풀이 코드의 Big-O 구하기
  • 강사님께 문의 드리기 (퀵소트 시간 복잡도)

오늘 한 일 (회고)

  • BinaryGap알고리즘 문제의 다른 사람 코드를 살펴보았다. strip(), split() 메소드를 사용해서 코드 1줄로 해결하는 풀이가 인상적이었다. (나는 왜 저런 식으로 접근하지 못했을까!) 충분히 고민을 해본 뒤에 잘하는 사람의 코드를 보면 항상 감탄하게 되고 배우는 것도 많은 것 같다.
  • 앞으로 알고리즘 문제를 풀면서 big-O를 함께 구해보려고 하는데, 내가 구한 Big-O가 맞는건지 모르겠다. 이 부분은 선생님께 조언을 들어봐야겠다. 찾아보니 코드를 넣으면 big-O를 자동으로 구해주거나 하는 프로그램은 없는 것 같다. (Big-O is easy to calculate, if you know how)
  • 컴퓨터 공학 입문 수업에 참여했다. (flask , sqlite db 사용)

내일 할 일

  • flask와 sqlite를 사용하여 연락처 웹페이지 만들기 (숙제)

4월 24일 (월)

오늘 할 일(계획)

오늘 한 일 (회고)

  • 컴퓨터 공학 입문 수업을 들었다.
    • 수업시간에 flask를 사용해 보았는데 router, view를 한번에 처리하고,
      startproject를 통해서 프로젝트 폴더 세트를 생성할 필요 없이 파이썬 파일 하나로 바로 서버를 띄울 수 있어서 간편하다고 느꼈다.
    • 웹 스크랩핑을 진행했다. 네이버 블로그 검색결과에서 제목과 링크만 가져오는 간단한 작업이었는데, 마치 DOM 탐색을 하는 것 같은 인상을 받았다. 잘 사용하면 아주 유용하겠다는 생각이 든다. AskDjango에서 크롤링 강의도 들어봐야지
  • 사용자가 업로드한 이미지 확장자를 바꾸고, png의 경우 압축률 지정을 통해서 용량을 줄일 수 있다는걸 배웠다.
    • 최근 영어 스터디 게시판에 이미지 업로드 기능을 추가했는데, 테스트로 unsplash 사이트의 고화질 대용량 사진을 올렸더니 로딩시간이 길어지는 문제가 있었다. 이미지 확장자를 png로 바꾸고 압축률을 지정해서 해결이 가능한지 확인해봐야겠다.
  • AskDjango 여행 블로그 만들기 실습을 시작했다.
  • github 커밋을 어떤 단위로 하는게 좋을까 감이 잘 잡히지 않는데, 강의 중에 커밋을 함께 진행하는 부분을 살펴보니 아래와 같은 규칙(?)을 발견 할 수 있었다.
    • 신규 model class 클래스를 추가 했을 때 (admin 등록 등 포함)
    • 기존 model class에 새로운 컬럼을 추가 했을 때
    • view에 FBV, CBV를 추가 했을 때 (template, url패턴 추가 수정 포함)

내일 할 일

강의노트 25. 자료구조, 알고리즘 - 성능측정 (Big-O)

|

패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

성능측정 - Big-O Notation

reference

Big-O Notation

시간복잡도

  • 실행 시간 이라는 관점에서 알고리즘의 효율을 측정한다.
  • 문제를 해결하려고 할 때마다 시간복잡도를 분석하는 습관을 들이면 좋은 개발자가 될 수 있다.
  • 이 때 중요한건 연산자의 숫자 혹은 연산 과정(step)의 수
  • 예를 들어 N이라는 인자가 주어졌을 때, 1부터 N까지를 더하는 함수 sumOfN을 정의한다.
def sumOfN(N):
  theSum = 0
  for i in range(1,N+1):
    theSum += i

  return theSum
  • 함수 sumOfN 에서 주요 연산 횟수를 살펴보면 아래와 같다.
def sumOfN(N):
  theSum = 0 # 1번만 실행된다.
  for i in range(1,N+1):
    theSum += i # N번 수행된다.

  return theSum
  • 함수 sumOfN 의 시간 복잡도는 아래 같이 표시할 수 있다.
    • T(n) = 1 + n
    • 파라미터 n 은 문제의 사이즈를 의미
    • T(n) 은 사이즈가 n 인 문제를 푸는데 걸리는 시간을 의미, 여기서는 즉 1 + n steps를 말한다.

Big-O

  • 그럼 문제의 사이즈 n에 따라서 알고리즘 수행 시간은 어떻게 달라질까?
  • 문제의 사이즈가 커질수록, 최고 차항의 차수가 결과에 가장 많은 영향을 미친다. (상기 예시에서는 1+n 중 n을 의미한다)
  • 이처럼 시간 복잡도에 가장 큰 영향을 미치는 차항으로 시간복잡도를 나타내는 것을 Big-O 표기법 (Big-O Notation) 이라고 하며, O(f(n)) 과 같이 표기한다. (O는 order 라고 읽는다.)
  • 시간 복잡도의 표현 법 중 가장 많이 쓰이는 표현 법으로 알고리즘 실행 시간의 상한을 나타낸 표기법이다. (최악의 효율)  
  • 간단한 Big-O 표기법의 예
T(n)=n^2+2n+9 # O(n2)

T(n)=n^4+n^3+n^2+1 # O(n4)

T(n)=5n^3+3n^2+2n+1 # O(n3)

worst case, average case, best case

  • 문제의 사이즈 보다, 데이터가 무엇이냐가 알고리즘의 성능에 더 영향을 미치기도 한다.
  • Big-O는 대부분 최악의 경우를 표현한다. (quick sort의 경우 예외적으로 average case를(O(N log N)) Big-O로 사용한다.)
def pick5(li):     # li = [5,3,1] 인 경우 1번만 반복
  for i in li:     # li = [1,5] 인 경우 2번 반복
    if i == 5:
      return

Big-O 표기법의 종류와 성능

Big-O 표기법의 종류

스크린샷 2017-04-30 오후 2.45.57

  • O(1) - (상수) Constant
    • 입력되는 데이터양과 상관없이 일정한 실행 시간을 가진다.
    • 알고리즘이 문제를 해결하는데 오직 한 단계만 거친다.
  • O(logN) Logarithmic
    • 데이터양이 많아져도, 시간이 조금씩 늘어난다.
    • 시간에 비례하여, 탐색 가능한 데이터양이 2의 n승이 된다.
    • 문제를 해결하는데 필요한 단계들이 연산마다 특정 요인에 의해 줄어든다.
    • 만약 입력 자료의 수에 따라 실행 시간이 이 log N 의 관계를 만족한다면 N이 증가함에 따라 실행시간이 조금씩 늘어난다. 이 유형은 주로 커다란 문제를 일정한 크기를 갖는 작은 문제로 쪼갤때 나타나는 유형이다.
    • Binary Search
  • O(N) Linear
    • 데이터양에 따라 시간이 정비례한다.
    • linear search, for 문을 통한 탐색을 생각하면 되겠다.
  • O(N log N) log linear
    • 데이터양이 N배 많이 진다면, 실행 시간은 N배 보다 조금더 많아 진다. (정비례 하지 않는다.)
    • 이 유형은 커다란 문제를 독립적인 작은 문제로 쪼개어 각각에 대해 독립적으로 해결하고,나중에 다시 그것들을 하나로 모으는 경우에 나타난다. N이 두배로 늘어나면 실행 시간은 2배보다 약간 더 많이 늘어난다.
    • 퀵소트, 머지소트
  • O(N^2) Quadratic
    • 데이터양에 따라 걸리는 시간은 제곱에 비례한다. (효율이 좋지 않음, 사용하면 안된다)
    • 이 유형은 이중루프내에서 입력 자료를 처리 하는 경우에 나타난다. N값이 큰값이 되면 실행 시간은 감당하지 못할 정도로 커지게 된다.
    • 문제를 해결하기 위한 단계의 수는 입력값 n의 제곱
    • 2중 for 문을 사용하는 버블소트, 삽입정렬(insertion sort)

성능비교

  • 성능 순서 : O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n) bigo_graph 스크린샷 2017-04-30 오후 2.54.04

실습

big-O 를 계산해보자!

  • 각 연산의 시간 복잡도를 계산하고 최종 시간복잡도를 big-O 로 표시해본다.
    a=5
    b=6
    c=10
    for i in range(n):
     for j in range(n):
        x = i * i
        y = j * j
        z = i * j
    for k in range(n):
     w = a*k + 45
     v = b*b
    d = 33
    
  • 각 연산 횟수를 더하면 시간 복잡도는 아래와 같다
  • T(n) = 3 + 3ㅜㅜn^2 + 2n + 1 = 3n^2 + 2n + 4
  • 이를 Big-O 로 표현하면 O(n^2) 이다.
    a=5 # Constant 1
    b=6 # Constant 1
    c=10 # Constant 1
    for i in range(n):
     for j in range(n):
        x = i * i # n^2 => for문 중첩 사용
        y = j * j # n^2
        z = i * j # n^2
    for k in range(n):
     w = a*k + 45 # n
     v = b*b # n
    d = 33 # Constant 1
    

self check

Write two Python functions to find the minimum number in a list.
The first function should compare each number to every other number on the list. O(n^2).
The second function should be linear O(n)

O(n^2)

# (O^2)
import time
from random import randrange


def findMin(alist):
    overallmin = alist[0]
    for i in alist:
        issmallest = True
        for j in alist: # O(n^2) => for문 중첩
            if i > j:
                issmallest = False
        if issmallest:
            overallmin = i
    return overallmin

# 확인
print(findMin([5,2,1,0]))
print(findMin([0,2,3,4]))

# 연산시간 (O(n^2))
for listSize in range(1000, 10001, 1000):
    alist = [randrange(100000) for _ in range(listSize)]
    start = time.time()
    print(findMin(alist))
    end = time.time()
    print("size: {}, time: {}".format(listSize, end-start))

O(n)


def findMin(alist):
    minsofar = alist[0]
    for i in alist: # O(n) alist의 길이만큼 반복, loop 중첩 없음   
        if i < minsofar:
            minsofar = i
    return minsofar

# 확인
print(findMin([5,2,1,0]))
print(findMin([0,2,3,4]))

# 연산시간 (O(n))
for listSize in range(1000, 10001, 1000):
    alist = [randrange(100000) for _ in range(listSize)]
    start = time.time()
    print(findMin(alist))
    end = time.time()
    print("size: {}, time: {}".format(listSize, end-start))

reference