[Python] [알고리즘] 5. 스택(3)
#합이 key인 부분집합 구하기
def f(i,k, key):
if i==k:
s = 0
for j in range(k):
if bit[j]:
s+=A[j]
if key == s: #합이 key와 같은 부분집합 출력
for j in range(k):
if bit[j]:
print(A[j], end = ' ')
print()
else:
bit[i] = 1
f(i+1, k, key)
bit[i] = 0
f(i+1,k, key)
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
bit = [0]*N
f(0,N, key)
def f(i,k):
if i==k: #하나의 부분집합 완성
for j in range(k):
if bit[j]:
print(A[j], end =' ')
print()
else:
bit[i] = 1
f(i+1,k)
bit[i] = 0
f(i+1,k)
A = [1,2,3]
N = len(A)
bit = [0]*N
f(0,N)
''' 출력
1 2 3
1 2
1 3
1
2 3
2
3
'''
def f(i,k):
if i==k:
s = 0
for j in range(k):
if bit[j]:
s+=A[j]
print(bit, s)
else:
bit[i] = 1
f(i+1,k)
bit[i] = 0
f(i+1,k)
A = [1,2,3]
N = len(A)
bit = [0]*N
f(0,N)
'''
[1, 1, 1] 6
[1, 1, 0] 3
[1, 0, 1] 4
[1, 0, 0] 1
[0, 1, 1] 5
[0, 1, 0] 2
[0, 0, 1] 3
[0, 0, 0] 0
'''
#합이 key인 부분집합의 존재 유무 파악하기
def f(i,k, key):
if i==k:
s = 0
for j in range(k):
if bit[j]:
s+=A[j]
if key == s:
return 1
return 0
else:
bit[i] = 1
if f(i+1, k, key):
return 1
bit[i] = 0
if f(i+1,k, key):
return 1
return 0
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
bit = [0]*N
print(f(0,N, key))
i번째 원소의 포함 여부에 따라 부분집합의 합이 달라진다. i번째 원소가 포함되지 않은 부분집합의 합을 Si라고 해보자. Si가 찾고자 하는 부분집합의 합보다 크다면 남은 원소를 고려할 필요가 없다.
def f(i,k,s,t): #i원소, k 집합의 크기, s i-1까지 고려한 집합의 합
global cnt
if i==k:
if s==t:
cnt+=1
return
else:
# bit[k] = 1
f(i+1,k,s+A[i],t) #A[i]를 포함
# bit[k] = 0
f(i+1,k,s,t) #A[i]를 미포함
#두 가지 경우에 대한 함수를 다 돌리기 때문에(가지가 뻗어 나가기 때문에)
#이 과정이 필수적이다. 만일 세 개의 가지가 뻗는다면 f가 3번 시행될 것.
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
cnt = 0
bit = [0]*N
f(0,N,0,key)
print(cnt) #합이 key인 부분집합의 수.
def f(i,k,s,t): #i원소, k 집합의 크기, s i-1까지 고려한 집합의 합
global cnt
global fcnt
fcnt+=1
if i==k:
if s==t:
for j in range(k):
if bit[j]:
print(A[j])
#print()
cnt+=1
return
else:
# s += A[i]
f(i+1,k,s+A[i],t) #A[i]를 포함
# bit[k] = 0
f(i+1,k,s,t) #A[i]를 미포함
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
cnt = 0
bit = [0]*N
fcnt = 0 #함수가 도는 수 세기
f(0,N,0,key)
print(cnt) #합이 key인 부분집합의 수
print(fcnt) #2047 출력
#출력은 적게 되는 거 같지만... fcnt가 2047번 돌고 있어서 매우 비효율적이다. 조건을 걸어주자.
#조건 걸어주기
def f(i,k,s,t): #i원소, k 집합의 크기, s i-1까지 고려한 집합의 합
global cnt
global fcnt
fcnt+=1
if s>t: #조건 걸기
return
if i==k:
if s==t:
for j in range(k):
if bit[j]:
print(A[j])
# print()
cnt+=1
return
else:
f(i+1,k,s+A[i],t) #A[i]를 포함
f(i+1,k,s,t) #A[i]를 미포함
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
cnt = 0
bit = [0]*N
fcnt = 0 #함수가 도는 수 세기
f(0,N,0,key)
print(cnt) #합이 key인 부분집합의 수
print(fcnt) #415 출력
def f(i,k,s,t): #i원소, k 집합의 크기, s i-1까지 고려한 집합의 합
global cnt
global fcnt
fcnt+=1
if s>t: #남은 원소가 고려할 필요가 없는 경우의 수
return
elif s==t: #남은 원소가 고려할 필요가 없는 경우의 수. 합을 찾았다.
cnt += 1
return
if i==k: #모든 원소가 고려된 것
if s==t:
for j in range(k):
if bit[j]:
cnt+=1
return
else:
f(i+1,k,s+A[i],t) #A[i]를 포함
f(i+1,k,s,t) #A[i]를 미포함
A = [1,2,3,4,5,6,7,8,9,10]
N = len(A)
key = 10
cnt = 0
bit = [0]*N
fcnt = 0 #함수가 도는 수 세기
f(0,N,0,key)
print(cnt) #합이 key인 부분집합의 수
print(fcnt) #349 출력
def f(i,k):
if i==k:
print(p)
else:
#자신을 i라고 하고, 바꿀 자리를 j라고 하자.
for j in range(k):
p[i], p[j] = p[j], p[i]
f(i+1,k)
p[i], p[j] = p[j], p[i]
p = [1,2,3]
N = len(p)
f(0, N)
+순열 만들기
nums = [20,30,40]
#goal = [20,30,40],[40,30,20],[30,20,40],...
def Permutation(k):
if k==N:
print(a)
for i in range(N):
idx = a[i]
print(nums[idx], end =' ')
for i in range(N):#원소가 3개일 경우 순열의 경우의 수는 3개가 되고, 4개일 경우 4개가 되고...
if not visited[i]:
visited[i] = True
a[k] = i
Permutation(k+1)
visited[i] = False
#다음 순열을 만들 때 지장받지 않기 위해서 visited를 원복시키는 것임. 차근차근 읽어보면 visited를 원복시켜도 결과에 악영향을 주지 않는다.
N = 3
a = [-1] * N
visited = [False] * N
Permutation(0)
분할 정복 알고리즘
분할: 해결할 문제를 여러 개의 작은 부분으로 나눈다.
정복: 나눈 작은 문제를 각각 해결한다.
통합: 해결된 해답을 모은다.
퀵 정렬
주어진 배열을 두 개로 분할하고, 각각을 정렬한다. 병합정렬과 다른 점은 병합정렬은 그냥 두 부분으로 나누는 반면, 퀵정렬은 분할할 때 기준 아이템 중심으로, 이보다 작은 건 왼편, 큰 건 오른편에 위치시킨다. 각 부분 정렬이 끝난 후, 병힙정렬은 ‘병합’이란 후처리 작업이 필요하나, 퀵정렬은 필요로 하지 않는다. 평균적으로 빠르게 진행되나 O는 n^2이다.
def quicksort(a,begin, end):
if begin < end:
p = partition(a,begin,end)
quicksort(a,begin,p-1) #피봇을 기준으로 왼쪽 정렬
quicksort(a,p+1,end) #피봇을 기준으로 오른쪽 정렬
def partition(a,begin, end):
pivot = (begin+end)//2
L = begin
R = end
while L<R:
while(L<R and a[L] < a[pivot]):
L += 1
while(L<R and a[R]>=a[pivot]):
R -= 1
if L<R:
if L==pivot: #L 영역에 피봇보다 작은 값만 모여 있다면
pivot = R
else:
a[L], a[R] = a[R], a[L]
a[pivot], a[R] = a[R], a[pivot]
return R'SSAFY > TIL' 카테고리의 다른 글
| [WEB] 1. HTML (0) | 2023.03.08 |
|---|---|
| [Python] [알고리즘] 6. 큐 (0) | 2023.02.20 |
| [Python] [알고리즘] 4. 스택(2) (0) | 2023.02.15 |
| [Python] [알고리즘] 3. 스택(1) (0) | 2023.02.15 |
| [Python] [알고리즘] 2. String (0) | 2023.02.14 |
TAGS.
