코딩 테스트
프로그래머스 level2 - 3 x n 타일링
ljs981026
2024. 12. 23. 10:17
문제 설명
가로 길이가 2이고 세로의 길이가 1인 직사각형 모양의 타일이 있습니다. 이 직사각형 타일을 이용하여 세로의 길이가 3이고 가로의 길이가 n인 바닥을 가득 채우려고 합니다. 타일을 채울 때는 다음과 같이 2가지 방법이 있습니다.
- 타일을 가로로 배치 하는 경우
- 타일을 세로로 배치 하는 경우
예를들어서 n이 8인 직사각형은 다음과 같이 채울 수 있습니다.
직사각형의 가로의 길이 n이 매개변수로 주어질 때, 이 직사각형을 채우는 방법의 수를 return 하는 solution 함수를 완성해주세요.
제한사항
- 가로의 길이 n은 5,000이하의 자연수 입니다.
- 경우의 수가 많아 질 수 있으므로, 경우의 수를 1,000,000,007으로 나눈 나머지를 return해주세요.
입출력 예
n | return |
4 | 11 |
문제 풀이
n = 1 일 때 경우의 수는 0가지
n = 2 일 때 경우의 수는 3가지
n = 3 일 때 경우의 수는 0가지
n = 4 일 때 경우의 수는 11가지
이 문제는 2 x n 타일링 문제와는 다르게 피보나치 수열로 해결할 수 없다. 그 이유는 2 x n 타일링 문제처럼 단순히 이전 두 상태로 현재 상태를 결정할 수 없고, n이 커질수록 더 복잡한 패턴과 경우의 수가 등장하기 때문에 더 많은 이전 상태를 참조해야한다.
점화식 설계
- 상태 정의
- dp[n]: 3 x n 바닥을 완전히 채우는 경우의 수
- 기본 규칙
- dp[0] = 1: 아무 타일도 없는 경우를 1가지 경우로 정의
- dp[1] = 0: 1 x 3은 채울 수 없음
- dp[2] = 3: 2 x 3은 타일 3개로만 채울 수 있음
- 점화식
- dp[n] = dp[n-2] * 3 + dp[n-4] * 2 + dp[n-6] * 2 + ...
- dp[n-2] * 3: 마지막 2칸에 특정 3가지 모양을 배치
- dp[n-4],dp[n-6]: 4칸, 6칸전에 추가적으로 등장하는 특별한 경우의 수
따라서 dp[n] = dp[n-2] * 3 + dp[n-4] * 2 + dp[n-6] * 2 + ... 해당 점화식을 코드로 구현하면 아래와 같다.
def solution(n):
if n == 2:
return 3
dp = [0] * (n+1)
dp[0] = 1
dp[2] = 3
mod = 1000000007
for i in range(4, n+1, 2):
dp[i] = dp[i-2] * 3
for j in range(i-4, -1, -2):
dp[i] += dp[j] * 2
dp[i] %= mod
return dp[n]
시간복잡도
- 바깥쪽 반복문: i는 4부터 n까지 2씩 증가하므로 총 n // 2 - 1번 실행되므로 O(n)
- 안쪽 반복문문: j는 i-4부터 0까지 2씩 감소하므로, i / 2 -2번 실행 됨
- 총 실행 횟수:
- 이 식은 에 비례한다. 따라서 전체 시간 복잡도는
공간복잡도
- 길이가 n + 1인 배열 선언
- 전체 공간복잡도는 O(n)
실행 결과
출처: https://school.programmers.co.kr/learn/courses/30/lessons/12902