Skip to content

2026-02-07 문제 풀었어요#28

Merged
uyeon0 merged 1 commit intomainfrom
upload
Feb 7, 2026
Merged

2026-02-07 문제 풀었어요#28
uyeon0 merged 1 commit intomainfrom
upload

Conversation

@uyeon0
Copy link
Collaborator

@uyeon0 uyeon0 commented Feb 7, 2026

User description

오늘도 멋져요 👍✨


PR Type

Enhancement


Description

  • 프로그래머스 72416 문제 (매출 하락 최소화) 해결

  • 복잡한 동적 프로그래밍 알고리즘 구현

  • 후위순회 기반 트리 순회 로직 적용


@uyeon0 uyeon0 added the programmers Programmers 문제 풀이 label Feb 7, 2026
@github-actions
Copy link

github-actions bot commented Feb 7, 2026

PR Reviewer Guide 🔍

🧪 No relevant tests
⚡ Recommended focus areas for review

복잡한 동적 프로그래밍

트리 기반 후위순회 동적 프로그래밍 알고리즘의 시간 및 공간 복잡도를 검토해야 합니다. 특히 최적의 팀원 선택 로직의 정확성을 확인해야 합니다.

// 3) dp 배열 준비 (1-indexed)
// dp0: v가 참석했을 때의 워크숍 참석 인원의 총 하루 평균 매출액 최솟값
// dp1: v가 참석하지 않았을 때의 워크숍 참석 인원의 총 하루 평균 매출액 최솟값
const dp0 = new Array(n + 1).fill(0);
const dp1 = new Array(n + 1).fill(0);

// 4) Bottom-up DP 계산 (order를 역순으로 돌면서 후위순회)
for (let i = order.length - 1; i >= 0; i--) {
  const v = order[i];
  const childs = children[v];

  // case 1) 리프인 경우 (순수 팀원인 경우)
  // - dp0[v] = sales[v] (본인이 참석)
  // - dp1[v] = 0 (본인 불참. 아래 팀이 없기 때문에 자식 중 한명이 꼭 참석해야 한다는 강제가 없다. 불참하면 끝.)
  if (childs.length === 0) {
    dp1[v] = sales[v - 1];
    dp0[v] = 0;
    continue;
  }

  // case 2) 팀장이고 팀원인 경우 (하위 팀이 있음)
  // a) 참석하는 경우 : 같은 팀의 다른 팀원들은 참석하든 안하든 상관 없음
  // -> dp1[v] = sales[v] + ∑ min(dp0, dp1)
  // b) 불참하는 경우 : 같은 팀의 다른 팀원 중 적어도 한명은 참석해야 함
  // -> 우선 모든 팀원들에서 가장 싼 상태를 더한 뒤 (sumMin)
  // -> 참석으로 돌렸을 때 비용이 가장 적게 추가되는 인원을 참석으로 돌린다. (extraMin)
  // -> dp0[v] = sumMin + extraMin
  let sumMin = 0;
  let extraMin = Infinity;

  for (const c of childs) {
    const m = Math.min(dp0[c], dp1[c]); // 참석하는 것과 안하는 것 중 최솟값
    sumMin += m;

    const extra = dp1[c] - m; // (참석으로 돌렸을 때 추가되는 비용)
    if (extra < extraMin) {
      extraMin = extra;
    }
  }

  dp1[v] = sales[v - 1] + sumMin;
  dp0[v] = sumMin + extraMin;
}
알고리즘 최적화

현재 구현된 알고리즘의 시간 복잡도는 O(n)이지만, 추가 최적화 가능성을 검토해야 합니다. 특히 extraMin 계산 로직의 효율성을 점검해야 합니다.

let sumMin = 0;
let extraMin = Infinity;

for (const c of childs) {
  const m = Math.min(dp0[c], dp1[c]); // 참석하는 것과 안하는 것 중 최솟값
  sumMin += m;

  const extra = dp1[c] - m; // (참석으로 돌렸을 때 추가되는 비용)
  if (extra < extraMin) {
    extraMin = extra;
  }
}

@github-actions
Copy link

github-actions bot commented Feb 7, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
재귀 기반 후위 순회로 코드 개선

현재 구현된 트리 순회 방식은 깊이 우선 탐색(DFS)의 역순으로 진행되어 후위 순회 효과를 내고 있습니다. 코드의 의도를 더 명확히 하기 위해
재귀적인 후위 순회 방식으로 리팩토링할 수 있습니다.

Programmers/Level4/72416_매출_하락_최소화.js [9-75]

 function solution(sales, links) {
   const n = sales.length;
-
-  // 1) 인접 리스트 구성
   const children = Array.from({ length: n + 1 }, () => []);
   for (const [a, b] of links) {
     children[a].push(b);
   }
 
-  // 2) 후위순회 준비
-  // NOTE: order를 역순으로 처리해서 postorder 효과를 낸다.
-  const order = [];
-  const stack = [1];
-  while (stack.length) {
-    const v = stack.pop();
-    order.push(v);
-    for (const c of children[v]) {
-      stack.push(c);
+  function postorderTraversal(node) {
+    if (children[node].length === 0) {
+      return [sales[node - 1], 0];
     }
+
+    let sumMin = 0;
+    let extraMin = Infinity;
+
+    for (const child of children[node]) {
+      const [childDp1, childDp0] = postorderTraversal(child);
+      const m = Math.min(childDp1, childDp0);
+      sumMin += m;
+
+      const extra = childDp0 - m;
+      extraMin = Math.min(extraMin, extra);
+    }
+
+    return [
+      sales[node - 1] + sumMin,
+      sumMin + extraMin
+    ];
   }
-  ...
+
+  const [dp1, dp0] = postorderTraversal(1);
+  return Math.min(dp1, dp0);
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion provides a more readable and conceptually clear recursive implementation of the post-order traversal. The refactored code maintains the same logic while improving code structure and readability of the solution function.

Medium

@yoouyeon yoouyeon added the ready-to-merge pr을 머지해주세요 label Feb 7, 2026
@uyeon0 uyeon0 merged commit 7fffe4e into main Feb 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

programmers Programmers 문제 풀이 ready-to-merge pr을 머지해주세요

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants