Динамическое программирование, рекурсия
Комбинация Сумма IV
다이나믹 프로그래밍 과 과 재귀 적 으로 배열 로 있는 있는 문제 로 숫자 로 로 로 있는 문제 을 을 숫자 로 로 을 을 을 을 이다 의 수 를 구하는 문제문제. ▼
다이나믹 프로그래밍 — снизу вверх
다이나믹 프로그래밍은 이전에 계산한 결과값을 저장해두었다가 다음 계산에 이용하는 프로그래밍 방식이다. 고등학교 때 배웠던 식끼리의 관계를 나타내주는 식인 점화식( A(n+1) = A(n)+A(n-1) )을 생각하면 흡사하다고 볼 수 있다.
다이나믹 프로그래밍은 сверху вниз 방식과 снизу вверх 방식으로 나누어 볼 수 있다. 아래는 снизу вверх 방식으로 푼 경우이다. снизу вверх 방식 은 주어진 숫자 배열 로 1 을 만드는 경우 의 수 시작 시작 하여 하여 하여 을 을 까지 하여 하여 하여 이라 을 고 수 까지 구하는 것 것 이라 고 할 수수 N-1, N-2, N-3.
Объяснение кода
- расческа 배열은 index를 만드는 경우의 수이다. 예를 들어 гребень[3]은 주어진 숫자들로 3을 만드는 경우의 수가 저장된다. 0을 만드는 경우의 수는 한가지이기 때문에 1을 저장하였다.
- 첫번째 for문은 снизу вверх방식으로 гребень[1] 부터 гребень[цель]까지 구하는 반복문이다.
- 두번째 for문에서는 гребень[i] += гребень[i — nums[j]] 점화식이 등장한다. 주어진 경우마다 target숫자에서 주어진 배열의 숫자를 뺀 차(i — nums[j])를 구한다. 이 차이를 매우는 경우의 수(comb[i — nums[j]]) 를 구하여 차례로 더해주면 된다. 직접 써보면 이해가 용이하다.
public class Solution { public int combinationSum4(int[] nums, int target) { int[] comb = new int[target + 1]; comb[0] = 1; for (int i = 1; i < comb.length; i++) { for (int j = 0; j < nums.length; j++) { if (i - nums[j] >= 0) { comb[i] += comb[i - nums[j]]; } } } return comb[target]; } }
재귀 방식
또 다른 풀이 방법으로는 재귀 방식(рекурсивный)이 있다. return 1을 해주는 조건을 지정하는 것이 포인트이다.
public int combinationSum4(int[] nums, int target) { if (target == 0) { return 1; } int res = 0; for (int i = 0; i < nums.length; i++) { if (target >= nums[i]) { res += combinationSum4(nums, target - nums[i]); } } return res; }
마무리
- 점화식을 이용해야한다는 느낌은 있었는데 점화식과 for문이 결합된 형태는 처음 접해보아 신툠선.
for (int j = 0; j < nums.length; j++) { if (i - nums[j] >= 0) { comb[i] += comb[i - nums[j]]; } }