•
회의 날짜: 2022/12/13
•
회의 장소: discord 라운지
•
참석자: 김솔배, 구연지, 안지영
[회고 사진]
[문제]
[이번 스터디 공부한 내용]
김솔배
•
DFS를 사용해서 먼저 풀어봤는데 시간초과가 났다.
•
BFS를 사용해도 시간초과가 났다…
•
그래서 for문을 통해 DP를 풀어봤다.
삼각형의 경로에서 거쳐간 숫자의 최댓값을 구해야한다.
dp배열을 만들어 이미 구한것은 중복되어 계산하지 않도록 했다.
BFS코드 (시간초과)
DFS코드 (시간초과)
해결코드
public class SolutionLoop {
private static int solution(int[][] triangle) {
int[][] dp = new int[triangle.length][triangle[triangle.length - 1].length];
dp[0][0] = triangle[0][0];
for (int i = 1; i < triangle.length; i++) {
for (int j = 0; j <= i; j++) {
if(j > 0)
dp[i][j] = dp[i - 1][j - 1] + triangle[i][j];
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j] + triangle[i][j]);
}
}
// System.out.println(Arrays.deepToString(dp));
int r = dp[triangle.length - 1][0];
for (int i = 1; i < triangle[triangle.length -1].length; ++i) {
r = Math.max(r, dp[triangle.length - 1][i]);
}
System.out.println(Arrays.deepToString(dp));
return r;
}
public static void main(String[] args) {
/*
* 7
* 3, 8
* 8, 1, 0
* 2, 7, 4, 4
* 4, 5, 2 ,6, 5
* */
int[][] triangle = new int[][]{{7}, {3, 8}, {8, 1, 0}, {2, 7, 4, 4}, {4, 5, 2, 6, 5}};
int result = solution(triangle);
System.out.println(result);
}
}
Java
복사
구연지
합이 최대인 경로 구하기 → N층에서의 최댓값을 구하려면 (N-1)층까지의 최댓값 + N층의 값 → 재귀 함수 또는 리스트에 기록하기: DP
1. 재귀 함수 이용하기
아래에서 한 층씩 올라가면서 최댓값을 재귀 함수를 이용해서 구하는 방법
제일 아래층은 그대로 return하고 그 위층은 아래 층의 두 수 중에서 큰 수를 return하여 합한다 → 이 때 행렬을 변화하는 것이 아니라 최댓 값들을 가지고 올라간다.
제일 위층까지 올라간 후 최댓값을 구한다.
2. 리스트에 기록하기
위에서 아래로 한 층 씩 내려오면서 최댓값을 구한다.
N층의 값들을 구하기 위해서는 N-1층에서의 최댓값들만 있으면 된다. 따라서 리스트에는 각 층을 내려오면서 변화한 값들만 기록한다.
이 때 삼각형의 왼쪽과 오른쪽 변(7,3,8,2,4와 7,8,0,4,5)는 한 곳에서만 값을 받을 수 있으므로 따로 체크한다.
(1) 재귀 함수 이용하기
def calculate_max_value(row, col, triangle):
if row == len(triangle)-1:
# depth가 1이라는 것은 가장 마지막 숫자들을 본다는 것
return triangle[row][col]
else:
num1 = calculate_max_value(row+1, col, triangle) + triangle[row][col]
num2 = calculate_max_value(row+1, col+1, triangle) + triangle[row][col]
return max(num1, num2)
# depth가 2 이상이면 col이 자기랑 같거나 자기보다 1 큰 경우 중에서 최댓값
def solution(triangle):
answer = calculate_max_value(0, 0, triangle)
return answer
print(solution([[7], [3, 8], [8, 1, 0], [2, 7, 4, 4], [4, 5, 2, 6, 5]]))
Python
복사
(2) 리스트에 기록하기
import copy
def solution(triangle):
# 층의 개수 = 숫자 개수
max_nums = [0]*len(triangle)
print(max_nums)
max_nums[0] = triangle[0][0]
print(max_nums)
for i in range(1,len(triangle)):
# 값을 업데이트하면서 N-1번째의 값이 소실될 수 있으므로 복사해둔다.
max_nums1 = copy.copy(max_nums)
# 삼각형의 왼쪽 변과 오른쪽 변
max_nums[0] = max_nums1[0] + triangle[i][0]
max_nums[i] = max_nums1[i-1] + triangle[i][i]
# 나머지
for j in range(1, i):
max_nums[j] = triangle[i][j] + max(max_nums1[j-1], max_nums1[j])
print(max_nums)
return max(max_nums)
print(solution([[7], [3, 8], [8, 1, 0], [2, 7, 4, 4], [4, 5, 2, 6, 5]]))
Python
복사
안지영
→ 위에서 부터 아래로 내려가면서 triangle 배열에 해당 노드까지의 경로 중 최댓값을 저장한다.
→ 대각선 방향으로 왼쪽/오른쪽으로만 이동이 가능하다는 점을 이용하면, 거쳐간 숫자의 합이 최대인 경로를 찾는 방법은 특정 노드를 기준으로 윗단의 왼쪽 노드, 오른쪽 노드까지의 숫자 합 중 최대인 것을 선택하는 것이다.
def solution(triangle):
for i in range(1,len(triangle)):
for j in range(len(triangle[i])):
left = triangle[i-1][j-1] if j-1 >= 0 else 0
right = triangle[i-1][j] if j < len(triangle[i-1]) else 0
triangle[i][j] += max(left,right)
return max(triangle[-1])
Python
복사
[어려웠던 부분]
•
점화식은 구현하였지만 코드로 풀어내는데 많이 고생했다.
생각에는 중복을 잘 제거한거같은데 자꾸 시간초과나 효율성 테스트에서 통과를 못했다.
HTML
복사
•
재귀 함수를 이용하는 경우는 시간 초과가 뜨는 경우가 많은 것 같고,
재귀 함수를 이용하지 않는(리스트에 기록하는) DP 기법이 문제 해결에 효과적이라는 것을 느꼈다
문제를 보고 Dynamic Programming이라는 생각이 든다면 어떻게 기록을 할 수 있을지를
생각해보는 것이 좋을 것 같다.
Plain Text
복사
•
어떤 값을 저장해야 하는지에 있어서 고민을 해야했다. 또한 dp 문제라는 걸 모르고 풀었을 때
풀 수 있을 지에 대한 자신은 조금 없는 것 같다.
Plain Text
복사
[금주의 꿀팁 & 인사이트!]
•
DP문제를 풀때는 어떻게 한번 구했던 값을 더 구하지 않을까라는 생각으로 접근하자
HTML
복사
•
문제를 보고 어떤 조건을 고려해야할 지 쉽게 떠오르지 않는다면
그림을 그려서 흐름이 어떻게 흘러가는지 알아보는 것도 좋은 것 같다.
Plain Text
복사
•
DP에서 어떤 값을 배열에 저장해 나갈지를 처음에 잘 정하는 게 중요한 것 같다.
Plain Text
복사
[금주의 느낀 점]
•
풀었던 코드를 다시한번 리펙토링해보는 시간은 갖자
HTML
복사
•
수업시간에 비슷한 문제를 풀어보아서 2번째 방법을 좀 더 쉽게 떠올릴 수 있었던 것 같다.
수업 시간에 배웠던 알고리즘 복습을 한 번 해보는 것도 좋지 않을까
Plain Text
복사
•
이름만 보고 가장 어려울 줄 알았는데 재귀가 들어간 dfs/bfs 이런 것 보다는 수월한 것 같다!
Plain Text
복사