stack=[]
stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
print(f'1st: {stack}')
stack.pop()
print(f'2nd: {stack}')
stack.append(1)
stack.append(4)
stack.pop()
print(f'3rd: {stack}')
print(f' 최상단: {stack[::-1]}') # 최상단 원소부터 출력
print(f' 최하단 : {stack}') # 최하단 원소부터 출력
1st: [5, 2, 3, 7]
2nd: [5, 2, 3]
3rd: [5, 2, 3, 1]
최상단: [1, 3, 2, 5]
최하단 : [5, 2, 3, 1]
from collections import deque
queue=deque()
queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
print(f'1st: {queue}')
queue.popleft() #popright도 가능
print(f'2nd: {queue}')
queue.append(1)
queue.append(4)
queue.popleft()
print(f'3rd: {queue}')
# 역순
queue.reverse()
print(f'reversed: {queue}')
1st: deque([5, 2, 3, 7])
2nd: deque([2, 3, 7])
3rd: deque([3, 7, 1, 4])
reversed: deque([4, 1, 7, 3])
https://velog.io/@lucky-korma/DFS-BFS%EC%9D%98-%EC%84%A4%EB%AA%85-%EC%B0%A8%EC%9D%B4%EC%A0%90
BFS: 가까운것부터 찾는다. 빠르다
DFS: 모든것
def recursive_fnc(i):
# 100번째 호출시 종료 되도록 조건 명시
if i==100:
return
print(f'{i}번째 재귀함수에서 {i+1}번째 재귀함수 호출')
recursive_fnc(i+1)
print(f'{i}번째 재귀함수를 종료')
recursive_fnc(1)
# 반복적으로 구현한 n!
def factorial_iterative(n):
res=1
# 1부터 n까지의 수를 차례로 곱하기
for i in range(1, n+1):
res*=i
return res
# 재귀적으로 구현한 n!
def factorial_iter(n):
if n<=1: # 0!과 1!은 1이므로
return 1
return n* factorial_iter(n-1)
print('반복적', factorial_iterative(5))
print('재귀적', factorial_iter(5))
반복적 120
재귀적 120
def gcd(a,b):
if a%b==0:
return b
else:
return gcd(b, a%b)
print(gcd(192,162))
6
# dfs 메소드 정의
def dfs(graph, v, visitied):
# 현재노드를 방문처리
visited[v]=True
print(v,end=' ')
# 현재노드와 연결된 다른 노드를 재귀적으로 방문
for i in graph[v]: # 노드별로 연결된 숫자들
if not visited[i]:
dfs(graph, i, visited)
# 노드정보 2차원 리스트
graph=[
[], # 인덱스 0은 비워둔다
[2,3,8], # 인덱스 1의 내용
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
# 노드가 방문된 정보 (1차원 리스트)
visited=[False]*9
dfs(graph, 1, visited)
1 2 7 6 8 3 4 5
from collections import deque
def bfs(graph, start, visited):
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
# 노드정보 2차원 리스트
graph=[
[],
[2,3,8],
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
# 노드가 방문된 정보 (1차원 리스트)
visited=[False]*9
bfs(graph, 1, visited)
1 2 3 8 7 4 5 6
n, m = map(int, input().split())
# 2차원 리스트의 맵 정보 입력 받기
graph = []
for i in range(n):
graph.append(list(map(int, input())))
# DFS로 특정한 노드를 방문한 뒤에 연결된 모든 노드들도 방문
def dfs(x, y):
# 주어진 범위를 벗어나는 경우에는 즉시 종료
if x <= -1 or x >= n or y <= -1 or y >= m:
return False
# 현재 노드를 아직 방문하지 않았다면
if graph[x][y] == 0:
# 해당 노드 방문 처리
graph[x][y] = 1
# 상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출
dfs(x - 1, y)
dfs(x, y - 1)
dfs(x + 1, y)
dfs(x, y + 1)
return True
return False
# 모든 노드(위치)에 대하여 음료수 채우기
result = 0
for i in range(n):
for j in range(m):
# 현재 위치에서 DFS 수행
if dfs(i, j) == True:
result += 1
print(result) # 정답 출력
3
[[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]] # graph
from collections import deque
# N, M을 공백을 기준으로 구분하여 입력 받기
n, m = map(int, input().split())
# 2차원 리스트의 맵 정보 입력 받기
graph = []
for i in range(n):
graph.append(list(map(int, input())))
# 이동할 네 가지 방향 정의 (상, 하, 좌, 우)
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
# BFS 소스코드 구현
def bfs(x, y):
# 큐(Queue) 구현을 위해 deque 라이브러리 사용
queue = deque()
queue.append((x, y))
# 큐가 빌 때까지 반복하기
while queue:
x, y = queue.popleft()
# 현재 위치에서 4가지 방향으로의 위치 확인
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
# 미로 찾기 공간을 벗어난 경우 무시
if nx < 0 or nx >= n or ny < 0 or ny >= m:
continue
# 벽인 경우 무시
if graph[nx][ny] == 0:
continue
# 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
if graph[nx][ny] == 1:
graph[nx][ny] = graph[x][y] + 1
queue.append((nx, ny))
# 가장 오른쪽 아래까지의 최단 거리 반환
return graph[n - 1][m - 1]
# BFS를 수행한 결과 출력
print(bfs(0, 0))
최적부분구조 (optimal substructure)
- 작은문제를 모아서 큰 문제 해결
중복되는 부분문제(overlapping subproblem)
-동일 작은문제 반복적 해결
# 피보나치수열 단순재귀
def fibo(x):
if x==1 or x==2:
return 1
return fibo(x-1)+fibo(x-2)
print(fibo(7))
13
d=[0]*100
def fibo(x):
if x==1 or x==2:
return 1
if d[x] !=0:
return d[x]
d[x]=fibo(x-1)+fibo(x-2)
return d[x]
print(fibo(99))
218922995834555169026
d=[0]*100
d[1]=1
d[2]=1
n=99
for i in range(3,n+1):
d[i]=d[i-1]+d[i-2]
print(d[n])
218922995834555169026
# 메모이제이션 이용시 피보나치 수열 함수시간 복잡도 O(N)
d=[0]*100
def fibo(x):
print(f'f({x})', end=' ')
if x==1 or x==2:
return 1
if d[x]!=0:
return d[x]
d[x]=fibo(x-1)+fibo(x-2)
return d[x]
fibo(6)
f(6) f(5) f(4) f(3) f(2) f(1) f(2) f(3) f(4)
8
분할정복에서 동일한 문제가 부분적으로 반복되지 않음
분할정복: 퀵정렬
가장 먼저 그리디, 구현, 완전탐색 등의 아이디어로 해결되는지 검토
=> 다른 풀이방법이 떠오르지 않으면 다이나믹프로그래밍
일단 재귀함수로 비효율적인 완전탐색 프로그램을 작성한 뒤(탑다운)
작은 문제에서 구한답이 큰 문제에서 그대로 사용 된다면 코드개선
일반적인 코테에서는 기본유형 다이나믹프로그래밍 문제가 출제되는 편
인접한 곳으로 갈 수 없음
입력조건:
-첫째줄에 식량창고의 개수 N이 주어짐( 3<=N<=100)
-둘째줄에 공백을 기준으로 각 식량창고에 저장된 식량의 개수K가 주어짐(0<=K<=1000)
출력조건:
-첫째줄에 개미전사가 얻을 수 있는 식량의 최대값을 출력하라
입력예시:
4
1 3 1 5
출력예시: 8
점화식
ai=max(a(i-1), a_(i-2)+k_i)
n=int(input())
array=list(map(int, input().split()))
# dp테이블 초기화
d=[0]*100
# 다이나믹 프로그래밍 진행(보텀업)
d[0]=array[0]
d[1]=max(array[0],array[1])
for i in range(2,n):
d[i]=max(d[i-1],d[i-2]+array[i])
print(d[n-1])
8
정수x가 주어졌을때, 4가지 연산을 통해 x를 1로 만들기
입력조건: 첫째줄에 정수 x가 주어집니다( 1<=x<=30,000)
출력조건: 첫째줄에 연산을 하는 횟수의 최솟값을 출력합니다
입력예시: 26
출력예시: 3
점화식
ai=min(a(i-1), a_i/2, a_i/3, a_i/5) +1 (단, 해당수의 배수여야 적용)
x=int(input())
d=[0]*30001
# 다이나믹 프로그래밍 진행(보텀업)
for i in range(2, x+1):
# 현재수에서 1을 빼는 경우
d[i]=d[i-1]+1
if i%2==0:
d[i]=min(d[i],d[i//2]+1)
if i%3==0:
d[i]=min(d[i],d[i//3]+1)
if i%5==0:
d[i]=min(d[i],d[i//5]+1)
print(d[x])
3
n,m=map(int,input().split())
array=[]
for i in range(n):
array.append(int(input()))
#dp초기화
d=[10001]*(m+1)
# 다이나믹 프로그래밍 진행 (보텀업)
d[0]=0
for i in range(n):
for j in range(array[i], m+1):
# (i-k) 만드는 방법이 없는 경우
if d[j-array[i]] !=10001:
d[j]=min(d[j], d[j- array[i]]+1)
# 최종적으로 M원을 만드는 방법이 없는 경우
if d[m]== 10001:
print(-1)
else:
print(d[m])
5
# 테스트케이스 입력
for tc in range(int(input())):
n,m=map(int, input().split())
array=list(map(int, input().split()))
dp=[]
idx=0
for i in range(n):
dp.appedn(array[idx:idx+m])
# 다이나믹 프로그래밍 진행
for j in range(1,m):
for i in range(n):
# 왼쪽 위에서 오는 경우
if i==0: left_up=0
else: left_up=dp[i+1][j-1]
# 왼쪽 아래에서
if i==n: left_down=0
else: left_down=dp[i+1][j-1]
# 왼쪽에서 오는 경우
left=dp[i][j-1]
dp[i][j]=dp[i][j]+ max(left_up, left_down, left)
result=0
for i in range(n):
result=max(result, dp[i][m-1])
print(result)
n=int(input())
array=list(map(int, input().split()))
# 순서를 뒤집어 '최장 증가 부분 수열 문제'로 변환
array.reverse()
dp=[1]*n
# LIS 수행
for i in range(1,n):
for j in range(0,i):
if array[j]< array[i]:
dp[i]=max(dp[i], dp[j]+1)
# 열외해야 하는 병사 최소수
print(n-max(dp))