python의 변수는 선언 없이 값이 할당되면 자동으로 타입이 결정됨.
x = 10 # 정수형 (int)
y = 3.14 # 실수형 (float)
z = "hello" # 문자열 (str)
a = True # 불리언 (bool)
b = None # NoneType
형 변환도 자유로움.
x = int("10") # 문자열 → 정수
y = float("3.14") # 문자열 → 실수
z = str(100) # 숫자 → 문자열
x = input()
보통 input()이 가장 많이 쓰이는 입력 함수지만, 코딩 테스트에서는 input()이 느린 편에 속함. 때문에 sys.stdin.readline을 사용하는 경우가 많음.
필자는 편하게 쓰려고
import sys
input = sys.stdin.readline
위와 같이 사용하는데 이렇게 하면 평소처럼 input()이라고 쓰고 사용할 수 있음.
x = input() # 실제론 x = sys.stdin.readline()
문제는 sys.stdin.readline()을 사용하면 입력을 받을 때 개행 문자 \n도 같이 입력받기 때문에 이를 없애려면 rstrip() 추가해주면 됨.
import sys
input = sys.stdin.readline
x = input().rstrip()
cf) SWEA에서는 import sys를 사용할 수 없게 막아두기 때문에 그냥 input()을 사용해야함. 왤까
일반적으로 입력을 받음과 동시에 타입을 선언해줌
x = int(input())
y = str(input())
코딩 테스트에서는 입력의 형태가 다음과 같은 경우가 많음.
이 경우는 리스트에 전부 저장해두거나, 전부 다른 변수에 저장할 수 있음.
필자는 보통 리스트에 저장함.
# 입력: 1 2 3 4 5
# 리스트에 저장
save = list(map(int, input().split()))
# 전부 다른 변수에 저장
a, b, c, d, e = map(int, input().split())
# 두 가지 모두 사용
save = list(map(int, input().split()))
a, b, c, d, e = save # 리스트에서 변수로 할당
이 경우는 리스트에 저장하는게 훨신 편함.
# 입력 총 5번
# 1
# 2
# 3
# 4
# 5
# 방법 1
save = []
n = int(input()) # 입력 개수
for i in range(5):
save.append(int(input()))
# 방법 2 (list comprehension, 조금 더 빠름)
n = int(input()) # 입력 개수
save = [int(input()) for _ in range(n)]
list comprehension은 자료구조 list 파트에 작성할 예정
print()
a = 3
print(f"a : {a}")
여러 줄의 답을 마지막에 한 번에 출력해야되는 경우가 있는데
(ex. 3줄 입력 받아 각각 연산하고 결과를 3줄 순서대로 출력)
필자는 아래와 같은 방식을 주로 쓴다.
answer = []
for _ in range(N):
# 연산 실행
answer.append(tmp)
print("\n".join(answer))
# 출력 결과
a #answer[0]
b #answer[1]
c #answer[2]
value = 3.141592
print(f"소수점 둘째 자리까지: {value:.2f}")
print(f"정수 5자리 확보: {42:05d}") # 5자리 확보 + 빈 자리 0 채우기
print(f"16진수 변환: {255:x}") # 16진수 변환
소수점 둘째 자리까지: 3.14
정수 5자리 확보: 00042
16진수 변환: ff
리스트(path)의 요소를 공백을 기준으로 나열하여 출력하는 문법
path = [1, 2, 3]
print(*path)
# 1 2 3
# print(" ".join(map(str, path))) 랑 결과가 같긴한데, *path가 더 빠름
path = [4, 5, 6]
print(*path, sep="-")
# 4-5-6
a = 5
b = 10
if a > 0 and b > 0:
print("둘 다 양수입니다")
if a > 0 or b < 0:
print("하나 이상이 양수입니다")
if not (a < 0):
print("a는 음수가 아닙니다")
arr = [1, 2, 3, 4, 5]
for num in arr:
print(num)
주로 range()랑 함께 사용
range(start, end, step)
for i in range(5): # 0부터 4까지 (5회)
print(i)
for i in range(1, 6): # 1부터 5까지
print(i)
for i in range(1, 10, 2):
print(i)
enumerate(): 리스트와 인덱스 값을 함께 가져오는 경우
arr = ["a", "b", "c"]
for index, value in enumerate(arr):
print(index, value)
# 0 a
# 1 b
# 2 c
zip(): 두 개 이상의 리스트를 동시에 순회할 때
arr1 = ["a", "b", "c"]
arr2 = [1, 2, 3]
for x, y in zip(arr1, arr2):
print(x, y)
# a 1
# b 2
# c 3
while (조건문):
~~~
while True:
~~~
break: 반복문 즉시 종료continue: 현재 반복 건너뛰고 다음 반복 실행arr = []
# 시간 복잡도: O(1)
arr = [1, 2, 3, 4, 5]
arr = [0] * N
# 시간 복잡도: O(N)
arr = list(range(N))
# 시간 복잡도: O(N)
arr = [i for i in range(N)]
# 시간 복잡도: O(N)
cf) numbers = list(map(int, input().split())은 시간 복잡도 O(N)
arr.append(n) # 마지막에 추가
# 시간 복잡도: O(1) ~ O(N)
arr.insert(n, 10) # n번 인덱스에 10 삽입
# 시간 복잡도: O(N)
arr.extend([a, b, c])
# 시간 복잡도: O(K), K는 추가할 원소 개수
arr.pop() # 마지막 원소 제거 후 반환
# 시간 복잡도: O(1)
arr.pop(i) # 인덱스 i의 원소 제거 후 반환
# 시간 복잡도: O(N)
arr.remove(x) # 값이 x인 첫 번째 원소 제거
# 시간 복잡도: O(N)
del arr[i] # 인덱스 i의 원소 삭제
# 시간 복잡도: O(N)
arr.clear() # 모든 원소 삭제
# 시간 복잡도: O(N)
arr[i] # 인덱스 i의 원소 접근
# 시간 복잡도: O(1)
arr[i] =. # 인덱스 i의 원소 변경
# 시간 복잡도: O(1)
x in arr # x가 리스트에 있는지 확인
# 시간 복잡도: O(N)
arr.index(x) # 값 x의 첫 번째 인덱스 반환
# 시간 복잡도: O(N)
arr.count(x) # 값 x의 개수 반환
# 시간 복잡도: O(N)
arr.sort() # 리스트 정렬(오름차순)
# 시간 복잡도: O(N log N)
arr.sort(reverse=True) # 리스트 정렬(내림차순)
# 시간 복잡도: O(N log N)
sorted(arr) # 정렬된 새 리스트 반환
# 시간 복잡도: O(N log N)
arr.reverse() # 리스트 뒤집기
# 시간 복잡도: O(N)
reversed(arr) # 뒤집힌 새 리스트 반환
# 시간 복잡도: O(N)
arr.copy() # 리스트 얕은 복사
# 시간 복잡도: O(N)
arr[:] # 리스트 얕은 복사(슬라이싱)
# 시간 복잡도: O(N)
list(arr) # 리스트 얕은 복사
# 시간 복잡도: O(N)
copy.deepcopy(arr) # 리스트 깊은 복사 (중첩 리스트 포함)
# 시간 복잡도: O(N)
list(map(int, input().split()) # 문자열 → 정수 리스트 변환
# 시간 복잡도: O(N)
list(str) # 문자열 → 리스트 변환
# 시간 복잡도: O(N)
''.join(arr) # 리스트 → 문자열 변환
# 시간 복잡도: O(N)
arr[start:end] # 부분 리스트 변환 (start ~ end - 1)
# 시간 복잡도: O(K), K는 슬라이스 크기
arr[start:end:step] # step 간격으로 슬라이싱
# 시간 복잡도: O(K)
arr.sort() # 오름차순
arr.sort(reverse=True) # 내림차순
arr.reverse() # 리스트 뒤집기
max(arr) # 최댓값 반환
# 시간 복잡도: O(N)
min(arr) # 최솟값 반환
# 시간 복잡도: O(N)
sum(arr) # 리스트 모든 원소의 합 반환
# 시간 복잡도: O(N)
math.prod(arr) # 리스트 모든 원소의 곱 반환 (Python 3.8 ~)
# 시간 복잡도: O(N)
len(arr) # 리스트 길이 반환
# 시간 복잡도: O(1)
all()
all()
# 리스트, 튜플과 같은 반환 가능한(iterable) 객체의 모든 요소가 True일 경우 True를 반환하는 내장 함수
# 리스트의 모든 요소가 특정 조건을 만족하는지 검사할 때 사용하면 좋음.
all([True, True, True]) # 모든 값이 True → True 반환
all([True, False, True]) # False가 포함 → False 반환
all([]) # 빈 리스트는 기본적으로 True 반환
# 시간 복잡도: O(N)
# 예시
nums = [2, 4, 6, 8]
print(all(num % 2 == 0 for num in nums)) # ✅ 모든 숫자가 짝수 → True 반환
nums = [2, 3, 6, 8]
print(all(num % 2 == 0 for num in nums)) # ❌ 홀수(3) 포함 → False 반환
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(matrix[0][1]) # 첫 번째 행, 두 번째 열 → 2
print(matrix[2][2]) # 세 번째 행, 세 번째 열 → 9
for row in matrix:
print(row)
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
for i in range(len(matrix)):
for j in range(len(matrix[0]):
print(matrix[i][j], end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9
len(matrix) : 행 개수
len(matrix[0]): 열 개수
그래프를 저장하는 방식 중 하나, DFS에서 주로 사용(메모리 효율이 좋고 탐색 속도가 빨라서)
1 -- 2 -- 5
| |
3 -- 4
graph = {
1: [2, 3], # 노드 1은 2, 3이랑 연결되어 있다는 뜻
2: [1, 4, 5],
3: [1, 4],
4: [2, 3],
5: [2]
}
graph[1] = [2, 3]
graph[2] = [1, 4, 5]
graph[n].append()
graph[n].remove()
graph[n] = [] → 노드 추가
시간복잡도: O(V + E)
V: 노드 개수, E: 간선 개수
graph = [
[0, 1, 1, 0, 0],
[1, 0, 0, 1, 1],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 0],
[0, 1, 0, 0, 0]
]
시간복잡도: O(1)
for 문을 한 줄로 작성하여 리스트를 만드는 방법.
append() 보다 효율적.
[표현식 for 변수 in 반복가능한객체]
표현식: 리스트에 추가할 값변수: for 문에서 순회하는 변수반복가능한객체: range(), 리스트, 문자열 등 순회 가능한 객체예시
numbers = [i for i in range(5)]
# numbers = [0, 1, 2, 3, 4]
N = int(input())
numbers = [int(input() for _ in range(N)]
# 여러 줄에 걸쳐 입력 받을 때
even_numbers = [i for i in range(10) if i % 2 == 0]
# numbers = [0, 2, 4, 6, 8]
numbers = ["짝" if i % 2 == 0 else "홀" for i in range(4)]
# numbers = ["짝", "홀", "짝", "홀" ]
중복 허용 X
s = {1, 2, 3, 4, 5}
s.add(6) # 요소 추가
s.remove(3) # 특정 값 제거
print(3 in s) # True, 존재 여부 확인
python에서는 queue를 구현할 때 주로 deque, heapq를 사용
d = { 'a' : 1, 'b' : 2}
d['c'] = 3
print(d['a']) # 1
print('b' in d) # True
from collections import defaultdict
d = defaultdict(int)
d['a'] += 1
d = defaultdict(int) # 숫자 카운팅
d = defaultdict(list) # 리스트 자동 생성
d = defaultdict(set) # set 자동 생성
import math
math.factorial(n) # n!
math.gcd(n, m) # n, m의 최대공약수
math.sqrt(n) # n의 제곱근
math.pow(n, m) # n^m
from itertools import permutations, combinations
arr = [1, 2, 3]
list(permutations(arr, n)) # 순열(순서 중요)
list(combinations(arr, n)) # 조합(순서 상관없음)
import heapq
pq = []
heapq.heappush(pq, 3)
heapq.heappush(pq, 1)
heapq.heappush(pq, 2)
heapq.heappop(pq) # 1, 가장 작은 값 출력
import bisect
arr = [1, 3, 5, 7, 9, 11, 13, 15]
target = 7
# 이진 탐색 실행
index = bisect.bisect_left(arr, target)
# 값이 존재하는지 확인
if index < len(arr) and arr[index] == target:
print(index) # 출력: 3
else:
print(-1) # 값이 없으면 -1 반환
<기본>
bisect_left(arr, x): x가 들어갈 가장 왼쪽 위치 반환bisect_right(arr, x): x가 들어갈 가장 오른쪽 위치 반환insort_left(arr, x): x를 arr에 삽입하며 정렬 유지(왼쪽 기준)insort_right(arr, x): x를 arr에 삽입하여 정렬 유지(오른쪽 기준)<응용>
bisect_right(arr, x) - bisect_left(arr, x): 정렬된 배열에서 x의 개수bisect_left(arr, x): x보다 작은 값들의 개수len(arr) - bisect_right(arr, x): x보다 큰 값들의 개수bisect_right(arr, x): x 이하 값들의 개수len(arr) - bisect_left(arr, x): x 이상 값들의 개수