코딩테스트 스터디를 시작했다. 언어는 파이썬으로 결정되었고, 백준과 프로그래머스 사이트 문제를 푸는것으로 좁혀졌다. 빨리 문제 풀기에 들어가고 싶어서 찾아보던 도중 코딩테스를 위한 파이썬 문법이 유튜브에 있어서 보고 팁을 정리했다.
동빈나 파이썬 코딩테스트
온라인 개발 환경 리플릿
리플릿
동빈나님의 팀 노트
팀 노트
특정한 크기의 입력에 대하여 알고리즘의 수행 시간 분석
특정한 크기의 입력에 대하여 알고리즘의 메모리 사용량 분석
가장 빠르게 증가하는 항만을 고려한다.
연산 횟수가 3N^3 + 5N^2 + 1,000,000 인 알고리즘이 있다면 빅오 표기법에서는 차수가 가장 큰 항만 남기므로 O(N^3)으로 표현된다.
O(1) > O(logN) > O(N) > O(NlogN) > O(N^2) > O(N^3) > O(2^n)
코테에서 시간제한은 통상 1~5초 가량이라고 생각하자. 문제에 시간제한이 명시되어 있지 않더라도 5초 안에 푸는게 합리적이다. PyPy를 지원하는 경우에는 때로는 C언어보다도 빠르지만 이를 항상 보장하지 않는다. 일반적으로 파이썬으로 먼저 제출 한 후에, 알고리즘에는 문제가 없는것 같다면 PyPy로 제출 해 보자.
시간제한이 1초인 문제를 만났을 때 일반적인 기준
N의 범위가 500인 경우 : 시간 복잡도가 O(N^3)인 알고리즘을 설계해야 한다.
N의 범위가 2000인 경우 : 시간 복잡도가 O(N^2)인 알고리즘을 설계해야 한다.
N의 범위가 100,000인 경우 : 시간 복잡도가 O(NlogN)인 알고리즘을 설계해야 한다.
N의 범위가 10,000,000인 경우 : 시간 복잡도가 O(N)인 알고리즘을 설계해야 한다.
import time
start_time = time.time() # 측정 시작
# 프로그램 소스코드
end_time = time.time() # 측정 종료
print("time:", end_time - start_time) # 수행 시간 출력
정수형, 실수형, 복소수형, 문자열, 리스트(c++의 vector가 제공하는 기능들을 내장), 튜플, 사전 등이 있다.
소수부가 0이거나, 정수부가 0인 소수는 0을 생략하고 작성할 수 있다. 실수 정보는 정확도에 한계를 가진다. 2진수 체계인 컴퓨터 시스템에서는 0.3 과 0.6을 더한 값은 0.9로 딱 떨어지지 않는다. 최대한 가깝게 표현하는 것 뿐이다.
a = 5. # 5.0
a = -.7 # -0.7
e나 E를 이용한 지수 표현 방식을 이용할 수 있다. e나 E 다음에 오는 수는 10의 지수부를 의미한다.
1e9 라고 입력한다면 이는 10의 9제곱인 1,000,000,000 이 된다.
나누기 연산자 / 는 나눠진 결과를 실수형으로 반환한다.
몫을 얻기 위해서 몫 연산자인 // 를 사용한다.
거듭제곱 연산자로 ** 가능하다.
여러개의 데이터를 연속적으로 담아 처리하기 위해 사용한다. 배열 혹인 테이블이라고도 불린다.
C++의 STL vector와 기능적으로 유사하다.
arr = list() # 혹은
arr = [1, 2, 3, 4, 5]
el = arr[1] # 2. 인덱싱이 가능하다.
el2 = arr[-2] # 음의 정수도 가능하다. -1이 마지막원소고, 거꾸로 탐색한다.
리스트에서 슬라이싱을 이용해서 시작인덱스 부터 끝 인덱스 -1 까지 원소를 가져올 수 있다.
arr = [1, 2, 3, 4, 5]
arr[1:4] # [2, 3, 4] # 인덱스 1 부터 3까지 가져온다.
리스트를 초기화하는 방법 중 하나이다.
arr = [i for i in range(1, 4)]
print(arr) # [1, 2, 3]
arr = [i for i in range(20) if i % 3 == 0]
print(arr) # 3의 배수 리스트 출력
# 2차원 리스트
n = 4
m = 3
arr = [n * [0] for _ in range(m)]
print(arr) # [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
append, sort, sort(reverse=True), reverse, insert, count, remove
a = [4, 3, 2, 1]
a.insert(2, 10) # 인덱스 2에 3을 추가한다. [4, 3, 10, 2, 1]
리스트에서 remove는 최초 하나의 값만 지워준다. 모두 제거하기 위한 방법으로 집합 자료형을 사용할 수 있다.
a = [1, 2, 3, 4, 5, 5, 5]
remove_set = { 3, 5 }
result = [i for i in a if i not in remove_set] # [1, 2, 4]
str = "string"
str*3 # "stringstringstring"
리스트와 유사하지만 한 번 선언된 값은 변경할 수 없다. 또한 소괄호를 이용한다.
리스트에 비해 상대적으로 공간 효율적이다.
서로 다른 성질의 데이터를 묶어서 관리해야 할 때
최단 경로 알고리즘에서 (비용, 노드번호) 형태로 튜플을 자주 사용한다.
데이터의 나열을 해싱의 키 값으로 사용해야 할 때
리스트 보다 메모리를 효율적으로 사용해야 할 때
str = '사과'
data = {
str: 'Apple',
'바나나': 'Banana'
}
print(data) # {'사과': 'Apple', '바나나': 'Banana'}
# 또는
data = dict()
data['사과'] = 'Apple'
data['바나나'] = 'Banana'
키 데이터만 뽑아서 리스트로 만들때는 keys() 함수를, 값 데이터만 뽑아서 리스트로 만들때는 values() 함수를 이용하자.
# 초기화
data = set([1, 2, 3, 4, 4, 4, 5]) # {1, 2, 3, 4, 5}. 4중복 제거
data = {1, 1, 2, 2, 3, 4, 4, 5, 5 } # {1, 2, 3, 4, 5}
합, 교, 차집합
a = {1, 2, 3, 4 }
b = {1, 4, 5, 6 }
# 합
a | b
#교
a & b
#차
a - b
data = set([1, 2, 3, 4, 5])
data.add(6)
# 새로운 원소 여러개 추가
data.update([7, 8])
data.remove(8)
이 둘은 순서가 없기 때문에 인덱싱으로 값을 얻을 수 없다.
사전의 키 혹은 집합의 원소를 이용해 O(1)의 시간 복잡도로 조회한다.
# 입력수가 적다면 (여기선 3개라면 3개로 언패킹한다.)
a, b, c = map(int, input().split())
# 많다면 list로 치환
data = list(map(int, input().split()))
최대한 빠르게 입력을 받아야 할 경우 sys 라이브러리에 정의되어 있는 sys.stdin.readline() 메서드를 사용한다.
입력 후 줄바꿈 처리 되므로 rstript() 메서드 함께 사용 해 주자.
import sys
data = sys.stdin.readline().rstrip()
print(data)
기본출력은 print() 함수다. print()는 기본적으로 출력 이후에 줄 바꿈을 수행한다. 줄바꿈을 원치 않는 경우 'end' 속성 사용한다.
print(8, end=" ")
answer = 7;
print(f"정답은 {answer}입니다.") # 수 데이터를 문자열로 치환하지 않고 사용 가능하다.
리스트, 튜플, 문자열, 딕셔너리 모두 사용 가능하다.
분기점에서 아무것도 처리하고 싶지 않을 때 사용할 수 있다.
if score >= 80:
pass
else:
print('성적이 80점 미만')
참인 경우가 앞에 쓰이고 조건문이 중간에 들어간다.
score = 85
result = "Success" if score >= 80 else "Fail"
a = 0
def func():
golbal a
a += 1
b = 10
def func2():
print(b+20)
arr = [1, 2 ,3, 4, 5]
def func3():
array.append(10)
파이썬에서 함수는 여러개의 반환 값을 가질 수 있다.
def operator(a, b):
add = a + b
subtract = a - b
multiply = a * b
divide = a / b
return add, substract, multiply, divide
a , b, c, d = operator(10, 3)
print((lambda a, b: a+ b)(3, 7)) # 10
여러개의 리스트에 적용
list1 = [1, 2, 3, 4, 5]
list2 = [6, 7, 8, 9, 10]
# 각각의 원소를 더한다.
result = list(map(lambda a,b: a + b, list1, list2))
print(result) # [7, 9, 11, 13, 15]
sum, min, max, eval(수식으로 표현된 식이 있을 때 계산한 결과를 반환), sorted(arr, key(정렬기준으로 일반적으로 람다), reverse),
서로 다른 n개에서 서로 다른 r개를 선택해서 일렬로 나열
{'A', 'B', 'B'}에서 세 개를 선택해 나열. 'ABC', 'ACB', 'BAC', 'BCA', 'CAB', 'CBA'
from itertools import permutations
data = ['A', 'B', 'C']
result = list(permutations(data, 3))
순서를 고려하고 중복을 허용해서 2개를 뽑는 모든 경우의 수
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
from itertools import product
data = ['A', 'B', 'C']
result = list(product(arr, repeat=2))
서로 다른 n개에서 순서에 상관 없이 서로 다른 r개를 선택하는 것
{'A', 'B', 'B'}에서 순서를 고려하지 않고 두 개를 뽑는 경우. 'AB', 'AC', 'BC'
from itertools import combinations
data = ['A', 'B', 'C']
result = list(combinations(data, 2))
순서에 상관없이 중복 허용해서 2개를 뽑는 모든 경우의 수
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
from itertools import combinations_with_replacement
result = list(combinations_with_replacement(arr, 2))
print(result)
collections 라이브러리의 Counter는 등장 횟수를 세는 기능을 제공한다. 리스트와 같은 반복 가능한 객체가 주어졌을 때 내부의 원소가 몇 번씩 등장했는지를 반환 해 준다.
from collections import Counter
arr = ['red', 'red', 'blue', 'blue', 'blue', 'blue']
counter = Counter(arr)
print(counter['red']) # 2
print(counter['blue']) # 4
math 라이브러리의 gdc() 함수를 이용할 수 있다.
import math
def lcm(a, b):
return a * b // math.gcd(a, b)
a = 21
b = 14
print(math.gcd(21, 14)) # 7
print(lcm(21,14)) # 42