문제 접근 및 공부 내용, 풀이는 모두 하단 코드에 "주석"으로 포함되어 있으니 참고해주세요.
문제 유형 보기
더보기
순열과 조합
https://dailyalgo.kr/ko/problems/99
https://dailyalgo.kr/ko/problems/100
https://dailyalgo.kr/ko/problems/101
https://dailyalgo.kr/ko/problems/102
순열과 조합 기본 유형 4문제라서 한꺼번에 묶었습니당~~~
순열
더보기
재귀로 직접 구현 풀이
def solution(n, m):
def permutations(current):
# 만약 목표 길이 도달했으면 -> return
# 아니라면 -> 계속 함수 실행
if len(current) == m:
# 참고로, 여기서 객체에다가 append 하는 거니까 값을 수정하는 게 아니기에,
# nonlocal answer은 필요 없음. 할당이 아니잖음.
# 여기 얕은 복사 해서 current와 같은 약은 복사 객체를 넣으면 됨.
answer.append(current[:])
# 아래처럼 했다면 그냥 '할당'이 돼버려서,
# answer[0]와 current가 같은 객체를 가리키는 변수가 돼버림.
# 정확히는, current가 가리키고 있는 같은 객체를 answer에 append 하는 것.
# answer.append(current)
return
# 사실상, 이게 취소한 것만 제외하면, 인접 리스트로 dfs 하는 거랑 똑같음 원리는
# 아닌 경우니까 -> 계속 함수 실행해야 함.
for i in range(1, n + 1):
# 아직 안 고른 수면 -> 추가하고 함수 실행
if not visited[i]:
# 일단 방문처리
visited[i] = True
current.append(i)
permutations(current)
# 뽑은 놈들 취소하기
visited[i] = False
current.pop()
# 중요!!! 여기 단계에서 실행하면 틀림.
# 얕은 복사가 필요한데, 그렇지 못해서, current가 저장된 모든 곳의 current가
# 같은 객체를 가리키는 변수였던 거임.
# 즉, 아래의 current와, answer[0]은 둘 다 똑같이 [1, 2]라는 동일한 객체를
# 포인팅하고 있는, 가리키고 있는 변수임.
# 즉, answer에 이미 append된 current가 아래 코드에서 같이 pop됨.
# current를 pop하니, answer[0] == [1, 2]가 [1]이 되고, 다시 []이 되는 거임.
# 따라서, 위에 answer에 넣을 때, 얕은 복사를 해서 넣으면 됨.
# numbers = [i for i in range(1, n+1)] -> 필요없어짐.
length = m
visited = [False] * (n + 1)
answer = []
permutations([])
# 참고로, 우린 따로 정렬할 필요가 x.
# 어차피 사전순대로 뽑게 되니까.
return answer
# [1, 2, ..., n]에 대해, nPm으로 가능한 모든 순열의 경우를 구하여라.
# answer = []
# current = [1, 2, 3]
# answer.append(current)
# -> answer[0], current는 둘 다 [1, 2, 3]이라는 객체를 가리키는 변수임.
itertools 모듈 사용 풀이
from itertools import permutations
def solution(n, m):
return [list(permutation) for permutation in permutations(range(1, n+1), m)]
250222 재풀이
재귀로 직접 구현 풀이
def solution(n, m):
def permutations(current):
# 1. 뽑고 싶은 만큼 뽑았다면 종료한다.
if len(current) == m:
answer.append(current[:])
return
# 2. 그렇지 않다면, 재귀를 돌면서 수를 더 뽑는다.
for i in range(1, n + 1):
if not visited[i]:
visited[i] = True
current.append(i)
permutations(current)
visited[i] = False
current.pop()
visited = [False] * (n + 1)
answer = []
permutations([])
return answer
itertools 모듈 사용 풀이
from itertools import permutations
def solution(n, m):
# return = list(map(list, permutations(range(1, n + 1), m)))
return [list(permutation) for permutation in permutations(range(1, n + 1), m)]
조합
더보기
재귀로 직접 구현 풀이
def solution(n, m):
def combinations(current, start):
if len(current) == m:
# 얕은 복사
answer.append(current[:])
return
for i in range(start, n + 1): # start ~ n까지이니까
current.append(i) # start ~ n까지이니까
combinations(current, i + 1)
current.pop()
answer = []
combinations([], 1)
return answer
# [1, 2, ..., n]에 대해, nCm을 한 모든 경우를 반환하라.
250222 재풀이
재귀로 직접 구현 풀이
def solution(n, m):
def combinations(current, start):
# 1. 뽑고 싶은 만큼 뽑았다면 종료한다.
if len(current) == m:
answer.append(current[:])
return
# 2. 그렇지 않다면, 재귀를 돌면서 수를 더 뽑는다.
for i in range(start, n + 1):
current.append(i)
combinations(current, i + 1)
current.pop()
answer = []
combinations([], 1)
return answer
itertools 모듈 사용 풀이
from itertools import combinations
def solution(n, m):
return [list(combination) for combination in combinations(range(1, n + 1), m)]
중복순열
더보기
재귀로 직접 구현 풀이
def solution(n, m):
def product(current):
# 만약 길이가 이미 다 찼으면:
if len(current) == m:
# 얕은 복사해서 current 집어넣음
answer.append(current[:])
# 다음 꺼 다룰 수 있게 return
return
# 만약 길이가 아직 다 안 찼으면:
for i in range(1, n + 1): # 1 ~ n 숫자로
# 중복 순열이니 i 앞에서부터 집어넣고
current.append(i)
# 그 집어넣어진 current로 다시 중복 순열 돌림
product(current)
# 그리고 다른 거 고려해줘야 하니까, pop 해야함
current.pop()
answer = []
product([])
return answer
# 1, 2, ..., n 중에서 m개를 중복 순열로 선택하는 숫자 집합 반환
# n파이m을 구해라.
250222 재풀이
재귀로 직접 구현 풀이
def solution(n, m):
def product(current):
# 1. 뽑을 만큼 뽑았다면 종료
if len(current) == m:
answer.append(current[:])
return
# 2. 그렇지 않다면, 재귀 돌며 계속 수를 뽑음.
for i in range(1, n + 1):
current.append(i)
product(current)
current.pop()
answer = []
product([])
return answer
itertools 모듈 사용 풀이
from itertools import product
def solution(n, m):
return [list(prod) for prod in product(range(1, n + 1), repeat = m)]
중복조합
더보기
재귀로 직접 구현 풀이
def solution(n, m):
def combinations_with_replacement(current, start):
if len(current) == m:
answer.append(current[:])
return
for i in range(start, n + 1):
current.append(i)
combinations_with_replacement(current, i)
current.pop()
answer = []
combinations_with_replacement([], 1)
return answer
# 1, 2, ..., n 중에서 m개의 숫자를 뽑을 건데,
# 보면 지금 순서를 고려하지 않고 뽑는 거임.
# 근데 중복은 허용함. 중복 조합 문제.
# 즉, nHm의 모든 가능한 숫자 집합을 반환하면 됨.
250222 재풀이
재귀로 직접 구현 풀이
def solution(n, m):
def combinations_with_replacement(current, start):
# 1. 뽑고 싶은 만큼 뽑았다면 종료
if len(current) == m:
answer.append(current[:])
return
# 2. 그렇지 않다면, 재귀 돌며 수를 계속 뽑음.
for i in range(start, n + 1):
current.append(i)
combinations_with_replacement(current, i)
current.pop()
answer = []
combinations_with_replacement([], 1)
return answer
itertools 모듈 사용 풀이
from itertools import combinations_with_replacement
def solution(n, m):
return [list(combination) for combination in combinations_with_replacement(range(1, n + 1), m)]
'Algorithms and Languages > 파이썬 알고리즘 문제풀이' 카테고리의 다른 글
[Python/백준] 7562. 나이트의 이동 (0) | 2025.02.21 |
---|---|
[Python/백준] 7569. 토마토 3차원 (0) | 2025.02.21 |
[Python/백준] 7576. 토마토 (0) | 2025.02.19 |
[Python/DailyAlgo] 65. 산불 조심 (0) | 2025.02.18 |
[Python/백준] 2667. 단지번호붙이기 (0) | 2025.02.18 |