PHM 2023. 9. 11. 16:56

기본 문법

- 진수 & 알파벳과 정수

# 16진수 변환
int(a, 16)

# 알파벳의 정수값
ord(x)

# 정수의 알파벳 값
chr(x)

 

- 반올림 값

print( format(x, ".2f") )

 

- 최대공약수와 최소공배수

import math

# 최대공약수
math.gcd(a,b)

# 최소공배수
(a * b) // math.gcd(a,b)

 

- i 부터 j 까지의 원소를 역순으로 변경

my_list[i:j+1] = reversed(my_list[i:j+1])

 

- exception 처리

try:
	# ...
except:
	# ...

 

- 삼항

(true logic) if (조건문) else (false logic)

 

- replace 키워드 ( 재저장해야한다 )

# 공백제거
replaced_a = a.replace(' ', '')

 

- 최소값과 최대값

min_value = 1e9
max_value = -1e9

...
min_value = min(min_value, now)
max_value = max(max_value, now)

 

- 람다 표현식

lambda arguments: expression
words = ["apple", "banana", "cherry", "date"]
words.sort(key=lambda word: len(word))
print(words)  # 출력: ['date', 'apple', 'banana', 'cherry']

 

- sort의 key 속성

'''
[정렬 기준]
1) 두 번째 원소를 기준으로 내림차순 정렬
2) 두 번째 원소가 같은 경우, 세 번째 원소를 기준으로 오름차순 정렬
3) 세 번째 원소가 같은 경우, 네 번째 원소를 기준으로 내림차순 정렬
4) 네 번째 원소가 같은 경우, 첫 번째 원소를 기준으로 오름차순 정렬
'''
students.sort(key=lambda x: (-int(x[1]), int(x[2]), -int(x[3]), x[0]))

    ㆍsort() 함수의 key 속성에 값을 대입하여 내가 원하는 '조건'에 맞게 튜플을 정렬시킬 수 있다는 점.

 

* 내가 생각하는 2차원 xy 좌표계가 아니라 xy가 바꼈다고 생각하자!!

# 2차원 리스트 선언
result = [[0] * 열수 for _ in range(행수)]

- N X M 크기의 2차원 리스트 초기화

array = [[0] * m for _ in range(n)]

 

- deque.rotate(x)

queue = deque(_list)

# x가 음수 일때는 맨앞값을 맨뒤로
# x가 양수 일때는 맨뒤값을 맨앞으로
queue.rotate(x)

 

- math.sqrt 는 float로 나온다! 주의할 것!

- 원 문제는 큐(queue)로 풀기

- 리스트보다는 딕셔너리가 더 빠르다.

 


이진탐색(이분탐색)

- 파이썬 이진 탐색 라이브러리

    ㆍbisect_left(a, x) : 정렬된 순서를 유지하면 배열 a에 x를 삽입할 가장 왼쪽 인덱스를 반환

    ㆍbisect_right(a, x) : 정렬된 순서를 유지하면서 배열 a에 x를 삽입할 가장 오른쪽에 인덱스를 반환

from bisect import bisect_left, bisect_right

a = [1,2,4,4,8]
x = 4

print(bisect_left(a, x))	# 2
print(bisect_right(a, x))	# 4
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

- 이진탐색 소스 코드 (재귀)

def binary_search(array, target, start, end):
    if start > end:
        return None
    mid = (start + end) // 2
    
    # 찾은 경우 중간점 인덱스 반환
    if array[mid] == target:
        return mid
        
    # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
    elif array[mid] > target:
        return binary_search(array, target, start, mid - 1)
        
    # 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
    else:
        return binary_search(array, target, mid + 1, end)

- 이진탐색 소스 코드 (반복문)

def binary_search(array, target, start, end):
    while start <= end:
        mid = (start + end) // 2

        # 찾은 경우 중간점 인덱스 반환
        if array[mid] == target:
            return mid

        # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
        elif array[mid] > target:
            end = mid - 1

        # 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
        else:
            start = mid + 1
    return None

 


DFS & BFS

- dfs (깊이 우선 탐색)

def dfs(graph, v, visited):
    # 현재 노드를 방문 처리
    visited[v] = True
    print(v, end=' ')
    # 현재 노드와 연결된 다른 노드를 재귀적으로 방문
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)

- bfs (너비 우선 탐색)

from collections import deque

# bfs 메서드 정의
def bfs(graph, start, visited):
    # 큐(Queue) 구현을 위해 deque 라이브러리 사용
    queue = deque([start])
    
    # 현재 노드를 방문 처리
    visited[start] = True
    
    # 큐가 빌 때까지 반복
    while queue:
        # 큐에서 하나의 원소를 뽑아 출력하기
        v = queue.popleft()
        print(v, end=' ')
        
        # 아직 방문하지 않은 인접한 원소들을 큐에 삽입
        for i in graph[v]:
            if not visited[i]:
                queue.append(i)
                visited[i] = True

* 모든 부분이 탐색될 시 DFS보단 BFS 추천!

* 그래프에서 모든 간선의 비용이 동일할 때는 너비 우선 탐색(BFS)을 이용해서 최단 거리를 찾을 수 있다.

 


순열과 조합

- r개의 데이터를 뽑아 일렬로 나열하는 모든 경우(순열)를 계산

from itertools import permutations

data = ['A', 'B', 'C']
result = list(permutations(data, 3))	# 모든 순열 구하기

print(result)
# [('A','B','C'),
#  ('A','C','B'),
#  ('B','A','C'),
#  ('B','C','A'),
#  ('C','A','B'),
#  ('C','B','A')]

- r개의 데이터를 뽑아 순서를 고려하지 않고 나열하는 모든 경우(조합)을 계산

from itertools import combinations

data = ['A', 'B', 'C']
result = list(combinations(data,2)) # 2개를 뽑는 모든 조합 구하기

print(result)	# [('A','B'), ('A','C'), ('B','C')]

- r 개의 데이터를 뽑아 일렬로 나열하는 모든 경우(순열)를 계산한다. 다만 원소를 중복하여 뽑는다.

from itertools import product

data = ['A', 'B', 'C']
result = list(product(data, repeat=2))	# 2개를 뽑는 모든 순열 구하기(중복허용)

 


최단 경로

- 다익스트라 알고리즘 ( 우선순위 큐 사용 X )

import sys
input = sys.stdin.readline
INF = int(1e9)

n, m = map(int, input().split())
start = int(input())
graph = [[] for i in range(n+1)]
visited = [False] * (n + 1)
distance = [INF] * (n + 1)

for _ in range(m):
    a,b,c = map(int, input().split())
    graph[a].append((b,c))

def get_smallest_node():
    min_value = INF
    index = 0
    for i in range(1, n+1):
        if distance[i] < min_value and not visited[i]:
            min_value = distance[i]
            index = i
    return index

def dijkstra(start):
    distance[start] = 0
    visited[start] = True
    for j in graph[start]:
        distance[j[0]] = j[1]
    for i in range(n-1):
        now = get_smallest_node()
        visited[now] = True
        
        for j in graph[now]:
            cost = distance[now] + j[1]
            if cost < distance[j[0]]:
                distance[j[0]] = cost

dijkstra(start)

for i in range(1, n+1):
    if distance[i] == INF:
        print("INFINITY")
    else:
        print(distance[i])

- 다익스트라 알고리즘 ( 우선순위 큐 사용 O )

import heapq
import sys
input = sys.stdin.readline
INF = int(1e9)

n, m = map(int, input().split())
start = int(input())
graph = [[] for i in range(n+1)]
distance = [INF] * (n+1)

for _ in range(m):
    a,b,c = map(int, input().split())
    graph[a].append((b,c))

def dijkstra(start):
    q = []
    heapq.heappush(q, (0, start))
    distance[start] = 0
    while q:
        dist, now = heapq.heappop(q)
        if distance[now] < dist:
            continue
        for i in graph[now]:
            cost = dist + i[1]
            if cost < distance[i[0]]:
                distance[i[0]] = cost
                heapq.heappush(q, (cost, i[0]))

dijkstra(start)

for i in range(1, n+1):
    if distance[i] == INF:
        print("INFINITY")
    else:
        print(distance[i])

- 플로이드 워셜 알고리즘

    ㆍO(N^3)

    ㆍ노드 수의 500개 이하될 때 사용

INF = int(1e9)

n = int(input())
m = int(input())
graph = [[INF] * (n + 1) for _ in range(n + 1)]

for a in range(1, n + 1):
    for b in range(1, n + 1):
        if a == b:
            graph[a][b] = 0

for _ in range(m):
    a,b,c = map(int, input().split())
    graph[a][b] = c

for k in range(1, n + 1):
    for a in range(1, n + 1):
        for b in range(1, n + 1):
            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])

for a in range(1, n + 1):
    for b in range(1, n + 1):
        if graph[a][b] == INF:
            print("INFINITY", end=" ")
        else:
            print(graph[a][b], end=" ")
    print()