알고리즘을 위한 기본적인 파이썬 문법(몰랐던 부분만 기록)
자료형
수 자료형
10억 -> 1e9와 같이 거듭제곱 표현 가능
컴퓨터는 실수를 정확히 표현하지 못한다. 그래서 실수 값을 제대로 비교하지 못해서 발생하는 에러들을 방지하기 위해 round()를 사용하는 것을 권장한다.
round(실수, 소수점) : 반올림
a = round(765.456, 2)
print(a)
# 결과
765.46
파이썬은 '/' 연산시 실수형 취급, 몫은 따로 '//' 연산자 사용
'**' : 거듭제곱 연산자
int의 범위 따로 고려x, int(data, radix)로 형변환 가능
ASCII(ord()) <-> 문자(chr()) : 서로 간 형변환
리스트 자료형
빈리스트: list() or [ ], 초기화 : a=[0]*n
슬라이싱 : a[1:4]
컴프리헨션 : a=[i for in range(1,10) if i&2==1]
- 2차원배열 초기화
a=[[0] * m for _ in range(n)]
- 반복문을 돌리면서 배열에 append 하는 방법도 있다.
array=[]
for i in range(4):
array.append(list(map(int,input().split())))
메서드 :
append(value), O(1)
sort() or (reverse=True), O(nlogn)
+) sorted()와의 차이점
- sorted는 기존 리스트를 변환하지 않고 정렬된 새로운 리스트를 반환한다.
- sort는 기존 리스트 자체를 정렬하여 변환한다.
reverse(), O(n)
insert(index, value), O(n)
count(value), O(n)
remove(value), O(n) : 값이 value인 원소가 여러개여도 1개만 제거 (제일 낮은 인덱스 value 제거)
-> 여러 개 remove : result=[i for i in list if i not in reverse_set] (reverse_set : values to be removed)
+) pop(index)
문자열 자료형
인덱싱, 슬라이싱 가능, but, 특정 index 값 변경 불가
''.join(리스트) : 리스트를 공백없이 문자열로 변환
str[::-1] : 문자열 역순
str.replace('from', 'to) : 특정 문자 다른 문자로 대체하기
문자열은 정렬이 되지 않는다.
문자열.isalpha() : 문자열이 알파벳으로 구성되어 있는지 확인하는 메소드(대소문자 관계 없다)
튜플 자료형
인덱싱, 슬라이싱 가능, but, 특정 index 값 변경 불가
리스트에 비해 공간 효율적이다.
서로 다른 성질의 데이터를 묶어서 관리해야 할 때 자주 사용한다.ex) 최단 경로 알고리즘 (비용, 노드 번호)
사전 자료형
데이터 검색 및 수정에 있어서 O(1)의 시간에 처리할 수 있다.
dict() or {key:value...}
key_list=data.key(), value_list=data.values()
-> dict_list의 형태이므로 list() 해주어야 list로 사용가능
집합 자료형
데이터 검색 및 수정에 있어서 O(1)의 시간에 처리할 수 있다.
set() or { }
'|', '&', '-', add(value), update([values, ...]), remove(value)
+) iterable 자료형의 크기는 len(iterable)로 구할 수 있다.
조건문
indent시 파이썬 표준은 tab이 아닌 space 4번
논리연산자 : and, or, not / in, not in
pass 키워드 : 아무것도 처리하지 않음(보통 debug시 사용) -> 파이썬은 if문의 내용이 꼭 있어야 한다.
조건부 표현식 : result="Success" if score>=80 else "Fail"
0<x<20 형태 사용 가능
반복문
while문
무한 루프 주의
for문
for i in (리스트, 튜플, 문자열 등) or range(start,end)
range는 증가값 설정 가능 -> range(start, end, 2)
for x, y in data : data에서 튜플과 같은 구조를 반복할 때 사용 가능하다.(각각 할당)
함수
def func(a,b): -> 직접 변수 지정 가능 : func(b=7,a=3)
함수에서 전역변수 사용시 global 키워드 사용, 단, 리스트의 경우 global 키워드 없어도 사용 가능
+) 파이썬은 기본적으로 함수 바깥의 변수를 함수 내부에서 사용 가능하다. 단, 변경은 불가하다. global을 붙여야 변경 가능하다.
+) 함수 안에서는 지역 변수를 우선적으로 처리한다.
여러 반환 값 가능 : overloading이 한 번에 packing, unpacking
(lambda a, b : a+b)(3 ,7)
응용:
array=[(a,1),(b,2).....], print(sorted(array,key=lambda x : x[1])) : sorting key 설정
result=list(map(lambda a, b:a+b, list1, list2)) : 두 리스트의 각 index의 value 값 더한 리스트 생성
입출력
data=list(map(int,input().split()) : 공백 기준 문자열 split + 한글자씩 split은 list(string)하면 된다.
a,b,c=map(int,input().split()) : packing -> unpacking
입력을 빠르게 받아야 하는 경우 : data=sys.stdin.readline().rstrip() (1000만 개가 넘는 라인이 입력 되는 경우 등)
- 혹은 input=sys.stdin.readline으로 명시하고 후에 input()을 사용하면 기존 input() 메서드처럼 사용 가능하다.
- 단, 문자열을 받을 때는 끝에 rstrip()을 붙여야 하는 것을 명시하자
출력 : print(a,b) : 자동 공백(a,b), 자동 줄바꿈 -> print(a,b,end=" ") : 자동 줄바꿈 x
python은 print() 시 문자열끼리만 '+' 연산 사용가능(!=java)
다양한 출력 방법 : print(f" ---- {int형} -----") or print("%d %d"%(n,m))
주요 라이브러리 문법과 유의점
<내장함수>
- sum(iterable 객체) (사전의 경우 key 기준), min(-,-,...), max(-,-,...), eval("수식"), abs(value)
- sorted(array, key=...., reverse=True) -> 리스트 반환
<itertools>
- from itertools import permutations
list(permutations(data,3)) -> 중복 포함 : product(data,repeat=3)
- from itertools import combinations
list(combinations(data,2)) -> 중복 포함 : combinations_with_replacement(data,2)
+) O(n!)이거나 근접한 복잡도로 효율적인 라이브러리는 아니다.
<heapq>
- import heapq
heapq.heappush(array,value), heapq.heappop(value) : 최소 heap 기준, 힙에 원소를 전부 넣었다가 빼도 O(nlogn)
+) heapq에서의 내용을 그대로 출력해보면 겉보기에 정렬되어 있지는 않다.
-> heap의 구조로 되어 있기 때문에 그 안에서 정렬이 이루어지는 것이지 리스트의 형태로 나열했을 때는 정렬되어 있지 않은 것으로 보이는 것이다.
heapq는 기본적으로 최소 힙이기 때문에, 최대 힙을 원한다면 부호를 바꿔서 push했다가 pop하고 다시 부호를 바꿔주면 된다.
<bisect>
- from bisect import bisect_left(bisect_right)
bisect_left(right)(array,value) : 사이 값 개수 구하는데 좋음, O(logn)
정렬된 리스트에서 값이 특정 범위에 속하는 원소의 개수를 구하고자 할 때, 효과적이다.
from bisect import bisect_left, bisect_right
# 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
def count_by_range(a,left_value,right_value):
right_index=bisect_right(a,right_value)
left_index=bisect_left(a,left_value)
return right_index-left_index
# 배열 선언
a = [1, 2, 3, 3, 3, 3, 4, 4, 8, 9]
# 값이 4인 데이터 개수 출력
print(count_by_range(a,4,4))
# 값이 [-1, 3] 범위에 있는 데이터 개수 출력
print(count_by_range(a,-1,3))
<collections>
- from collections import deque
deque(iterable) : 일반 리스트에 appendleft, popleft 추가(스택, 큐와 같이 원하는대로 사용 가능)
가장 앞쪽에 있는 원소를 추가하거나 제거해도 O(1)이다.
deque를 리스트로 사용하고 싶다면 list(deque)하면 된다.
- from collections import Counter
Counter(iterable) -> O(n)
dict(Counter(iterable))로 사전으로 변환 가능
<math>
- import math
math.factorial(value), .sqrt(value), .gcd(a,b), .pi, .e ....
<copy>
- import copy
1. 단순 객체 복사
파이썬에서 리스트와 같은 변경가능(mutable) 객체는 '=' 연산자로 복사를 하면 동일한 객체로 취급한다.
a=[1,2,3,4]
b=a
b[0]=5
print(a)
[5, 2, 3, 4]
그래서 만약 위와 같이 코드를 작성하면 b 리스트의 값을 변경할 때 a의 값도 같이 변경된다. 아마 이런 방식은 알고리즘을 작성할 때 원하는 바가 아닐 것이다.
2. 얇은 복사(shallow copy)
얇은 복사는 리스트는 별도로 생성하지만 그 안에 들어가는 내용은 원래와 같은 객체라는 점이다.
import copy
a = [1, [1, 2, 3]]
b = copy.copy(a) # shallow copy 발생
print(b) # [1, [1, 2, 3]] 출력
b[0] = 100
print(b) # [100, [1, 2, 3]] 출력,
print(a) # [1, [1, 2, 3]] 출력, shallow copy 가 발생해 복사된 리스트는 별도의 객체이므로 item을 수정하면 복사본만 수정된다. (immutable 객체의 경우)
c = copy.copy(a)
c[1].append(4) # 리스트의 두번째 item(내부리스트)에 4를 추가
print(c) # [1, [1, 2, 3, 4]] 출력
print(a) # [1, [1, 2, 3, 4]] 출력, a가 c와 똑같이 수정된 이유는 리스트의 item 내부의 객체는 동일한 객체이므로 mutable한 리스트를 수정할때는 둘다 값이 변경됨
3. 깊은 복사(deep copy)
mutable한 내부객체의 문제를 해결하기 위해서는 깊은 복사를 해야 한다. 깊은 복사는 리스트를 새롭게 생성하고 그 안의 내용까지 재귀적으로 새롭게 생성한다.
import copy
a = [1, [1, 2, 3]]
b = copy.deepcopy(a) # deep copy 실행
print(b) # [1, [1, 2, 3]] 출력
b[0] = 100
b[1].append(4)
print(b) # [100, [1, 2, 3, 4]] 출력
print(a) # [1, [1, 2, 3]] 출력
일반적으로 알고리즘에서 기존 데이터의 테스트용으로 사용하기 위해 깊은 복사를 원하는 경우가 많다.
'python > python' 카테고리의 다른 글
우선순위 큐 (0) | 2021.02.09 |
---|---|
이진 탐색 트리 (0) | 2021.02.09 |
그래프 (0) | 2021.02.09 |
재귀함수 (0) | 2021.02.09 |
스택 & 큐 (0) | 2021.02.09 |