티스토리 뷰
+ 추가가능한 부분
- [순열] 서로 자리를 바꾸어 순열을 만드는 알고리즘으로 시간복잡도 최소화
- [조합] n개에서 r개를 택할 때, r의 갯수를 하나씩 줄여가며 재귀로 푸는방식 (nCr = n-1Cr-1 + n-1Cr 활용)
순열(Permutation)과 조합(Combination)
- 순열 : 서로 다른 n개의 원소를 가진 집합에서 r개를 선택하여 순서대로 배열한다.
- 조합 : 서로 다른 n개의 원소를 가진 집합에서 r개를 선택하여 그룹을 만든다.
차이점은 순열은 수를 뽑은 후 순서를 생각해야 하지만 조합은 뽑은 것으로 끝난다는 것이다.
내장 패키지 모듈 또는 재귀로 구현할 수 있다.
순열은 어느정도 이해가 되었는데 조합은 조건부분을 아직 완전히 이해하진 못했다.
내장 패키지 모듈 사용 - 순열
from itertools import permutations
arr = [1, 2, 3, 4]
print(list(permutations(arr, 3)))
# 4 * 3 * 2 총 24개
# [(1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 4), (1, 4, 2), (1, 4, 3), (2, 1, 3), (2, 1, 4),
# (2, 3, 1), (2, 3, 4), (2, 4, 1), (2, 4, 3), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 2, 4),
# (3, 4, 1), (3, 4, 2), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 2, 3), (4, 3, 1), (4, 3, 2)]
재귀 사용 - 순열
- 리스트에서 r개를 뽑아 순열로 만든다.
- DFS로 구현한다.
- 글로벌 변수 미사용시 -
def permutation(arr, r):
# 사용된 원소를 저장할 배열을 만든다.
arr = sorted(arr)
used = [0 for _ in range(len(arr))]
def generate(chosen, used):
# 선택리스트에 순열의 원소를 저장하다가 갯수가 r개가 되면 출력 후 함수를 종료한다.
if len(chosen) == r:
print(chosen)
return
# 반복문을 돌면서
for i in range(len(arr)):
# 아직 사용하지 않았다면
if not used[i]:
# 선택리스트에 저장하고 방문체크한다.
chosen.append(arr[i])
used[i] = 1
# 다시 generate 함수를 반복한다.
generate(chosen, used)
# 하나의 순열이 만들어지면 다시 uncheck한다.
used[i] = 0
chosen.pop()
generate([], used)
permutation([1, 2, 3, 4], 3)
- 글로벌 변수 사용시 -
def permutation(arr, r):
global chosen, used
# 선택리스트에 순열의 원소를 저장하다가 갯수가 r개가 되면 출력 후 함수를 종료한다.
if len(chosen) == r:
print(chosen)
return
# 반복문을 돌면서
for i in range(len(arr)):
# 아직 사용하지 않았다면
if not used[i]:
# 선택리스트에 저장하고 방문체크한다.
chosen.append(arr[i])
used[i] = 1
# 다시 generate 함수를 반복한다.
permutation(arr, r)
# 하나의 순열이 만들어지면 다시 uncheck한다.
used[i] = 0
chosen.pop()
arr = [1, 2, 3, 4]
chosen = []
used = [0 for _ in range(len(arr))]
permutation(arr, 3)
- 전체 순열을 뽑는 경우(r개가 아닌 전체) -
# DFS로 모든 경우의 수를 하나씩 구하되, 각 경우의 수에 같은 요소가 없도록 함으로써 순열을 구현한다
l = ['a', 'b', 'c']
visited = [0 for _ in range(len(l))]
answer = []
def dfs(cnt, list):
if cnt == len(l):
answer.append(list[:])
return
for i, val in enumerate(l):
# 만약 방문했다면 건너 뛰기(순열을 위함)
if visited[i] == 1:
continue
# 현재까지의 list에 값을 추가하고, 방문 표시하기
list.append(val)
visited[i] = 1
dfs(cnt+1, list)
# 방금 전 list에 추가한 값과 방문 한 것을 되돌려주기
list.pop()
visited[i] = 0
dfs(0, [])
print(answer)
내장 패키지 모듈 사용 - 조합
from itertools import combinations
arr = [1, 2, 3, 4]
print(list(combinations(arr, 3)))
# (4 * 3 * 2) / (3 * 2) 총 4개
# [(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
재귀사용 - 조합
- 리스트에서 r개를 뽑아 조합을 만든다.
- DFS 구현 (응??이렇게 간단하다고?) -
l = [1, 2, 3, 4]
n = len(l)
r = 3
answer = []
def dfs(idx, list):
if len(list) == r:
answer.append(list[:])
return
for i in range(idx, n):
dfs(i+1,list+[l[i]])
dfs(0, [])
print(answer)
- 글로벌 변수 미사용시 -
def combination(arr, r):
# 사용된 원소를 저장할 배열을 만든다.
arr = sorted(arr)
used = [0 for _ in range(len(arr))]
# 선택리스트에 조의 원소를 저장하다가 갯수가 r개가 되면 출력 후 함수를 종료한다.
def generate(chosen):
if len(chosen) == r:
print(chosen)
return
# chosen(뽑은 조합 원소)가 없으면 start = 0으로
# 그 외에는 뽑은 조합의 가장 마지막 요소를 값의 인덱스 출력
# arr = [1, 2, 3, 4]
# 예를들어 chosen = [1, 2]를 뽑은 상태라면 start = arr.index(2) 이므로 1이고
# 거기에 1을 더해 최종 : 2
start = arr.index(chosen[-1]) + 1 if chosen else 0
# nxt = 2부터 시작
for nxt in range(start, len(arr)):
# 만약 아직 뽑지 않았고, ~~ 조건이라면
if used[nxt] == 0 and (nxt == 0 or arr[nxt-1] != arr[nxt] or used[nxt-1]):
# if used[nxt] == 0 :
# 다음 요소를 뽑고 방문처리한다.
chosen.append(arr[nxt])
used[nxt] = 1
# 다 뽑았으면 마지막 요소부터 pop하고 방문해제한다.
generate(chosen)
chosen.pop()
used[nxt] = 0
generate([])
combination([1, 2, 3, 4], 3)
- 글로벌 변수 사용시 -
def combination(arr, r):
global chosen, used
# 선택리스트에 조의 원소를 저장하다가 갯수가 r개가 되면 출력 후 함수를 종료한다.
if len(chosen) == r:
print(chosen)
return
# chosen(뽑은 조합 원소)가 없으면 start = 0으로
# 그 외에는 뽑은 조합의 가장 마지막 요소를 값의 인덱스 출력
start = arr.index(chosen[-1]) + 1 if chosen else 0
for nxt in range(start, len(arr)):
# 만약 아직 뽑지 않았고, ~~ 조건이라면
if used[nxt] == 0 and (nxt == 0 or arr[nxt-1] != arr[nxt] or used[nxt-1]):
# 다음 요소를 뽑고 방문처리한다.
chosen.append(arr[nxt])
used[nxt] = 1
# 다 뽑았으면 마지막 요소부터 pop하고 방문해제한다.
combination(arr, r)
chosen.pop()
used[nxt] = 0
arr = [1, 2, 3, 4]
chosen = []
used = [0 for _ in range(len(arr))]
combination(arr, 3)
코드 참조 : https://shoark7.github.io/programming/algorithm/Permutations-and-Combinations
중복순열
- 중복순열(n Π r): 서로 다른 n개에서 중복을 허락하여 r개를 선택하여 일렬로 나열한다.
- 예시
- 서로 다른 편지 3통을 서로 다른 2개의 우체통에 넣는 방법의 수는?
- 편지 = (움직이므로) 정의역 r , 우체통 = (움직이지 않으므로)공역 n
- 정의역에서 공역으로 대응되므로 n Π r => 2 Π 3
- 따라서 8가지
- 서로 다른 편지 3통을 서로 다른 2개의 우체통에 넣는 방법의 수는?
- 파이썬 라이브러리 활용하기
from itertools import product
mylist = [1, 2, 3]
print(list(product(mylist, repeat = 3)))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 3, 1), (1, 3, 2), (1, 3, 3), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 3, 1), (2, 3, 2), (2, 3, 3), (3, 1, 1), (3, 1, 2), (3, 1, 3), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 3, 1), (3, 3, 2), (3, 3, 3)]
중복조합
- 중복조합(n H r): 서로 다른 n개에서 중복을 허락하여 r개를 선택한다. (r > n 가능)
- 예시
- 세 개의 숫자 1, 2, 3에서 중복을 허용하여 6개의 숫자를 선택하는 방법.
- 6개의 숫자와 (3-1)개의 가림막(구분선) 즉 8개의 자리에 타겟을 놓을 6개의 자리를 택하는 조합의 수
- 따라서 3H6 = 8C6
- r개의 타겟과 (n-1)개의 구분선 , nHr = n+r-1Cr
- 세 개의 숫자 1, 2, 3에서 중복을 허용하여 6개의 숫자를 선택하는 방법.
- 파이썬 라이브러리 활용하기
from itertools import combinations_with_replacement
mylist = [1, 2, 3]
print(list(combinations_with_replacement(mylist, r = 3)))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 2), (1, 2, 3), (1, 3, 3), (2, 2, 2), (2, 2, 3), (2, 3, 3), (3, 3, 3)]
'Algorithm' 카테고리의 다른 글
[SWEA][stack] 4875_미로 (211018) (0) | 2021.10.18 |
---|---|
[분할정복] 합병정렬(Merge Sort) 구현 및 시간복잡도 증명하기 (1) | 2021.10.17 |
최단 경로와 다익스트라 알고리즘(Dijkstra Shortcut Path) (0) | 2021.10.16 |
서로소 집합과 MST 최소신장트리 / 프림 & 크루스칼 알고리즘 (0) | 2021.10.15 |
[SWEA] 2814. 최장 경로 D3 (0) | 2021.10.14 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 깃허브계정
- 상업용무료폰트
- ssafy6기
- 개발자
- 맥과윈도우로깃허브
- 무료폰트추천
- 개발도서추천
- 폰트
- 코딩도서
- 개발자도서추천
- 브왈라
- 깃허브계정2개
- SSAFY
- ssafy합격후기
- intj여자
- 폰트추천
- 개발언어추천
- ssafy후기
- 개발자책추천
- 개발자커리
- 싸피
- 임대차3법
- 개발언어순위
- 한글무료폰트추천
- 싸피6기
- 개발자로드맵
- 클린코더
- 클린코드
- ssafy결과
- 디즈니얼굴
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함