Post

가장 많이 받은 선물 비교

1월에 풀었던 문제를 다른 방법으로 다시 풀었고 작성한 코드를 비교한 글

https://school.programmers.co.kr/learn/courses/30/lessons/258712?language=javascript

1월에 푼 내용 정리

1월에 작성했던 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function solution(friends, gifts) {
  let answer = 0;

  // giftCount : 선물 지수, 선물 현황 리스트
  const giftCount = {};
  friends.forEach((f) => {
    giftCount[f] = { count: 0, list: {} };
  });

  // 선물 지수 및 선물 현황 계산
  gifts.forEach((gift) => {
    const [g, r] = gift.split(" ");
    giftCount[g].count += 1;
    giftCount[r].count -= 1;

    if (!giftCount[g].list[r]) {
      giftCount[g].list[r] = 0;
    }
    giftCount[g].list[r] += 1;
  });

  // 선물 지수 확인
  for (let i = 0; i < friends.length; i++) {
    let num = 0;
    for (let j = 0; j < friends.length; j++) {
      if (i === j) {
        continue;
      }
      const aName = friends[i];
      const bName = friends[j];

      const { count: aCount, list: aList } = giftCount[aName];
      const { count: bCount, list: bList } = giftCount[bName];

      // 선물을 주고 받았는지 확인
      const aToB = aList[bName] ? aList[bName] : 0;
      const bToA = bList[aName] ? bList[aName] : 0;

      // 선물 지수도 같고, 주고 받은 기록이 없음!
      if (aCount === bCount && aToB === 0 && bToA === 0) {
        continue;
      }
      // 선물을 주고 받은 적이 없거나 주고 받은 수가 같으면? => 선물 지수가 더 높은 사람
      if ((aToB === 0 && bToA === 0) || aToB === bToA) {
        if (aCount > bCount) {
          num += 1;
        }
      }
      // 선물을 더 많이 준 사람
      if (aToB > bToA) {
        num += 1;
      }
    }
    answer = Math.max(answer, num);
  }

  return answer;
}

7월에 작성한 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function solution(friends, gifts) {
  // 선물을 주고 받은 기록, 선물지수를 정리
  const giftRecords = {};
  const giftScores = {};
  const nextMonthReceivers = {};

  // 오브젝트 초기화
  for (let i = 0; i < friends.length; i++) {
    const friend = friends[i];

    giftRecords[friend] = {};
    giftScores[friend] = 0;
    nextMonthReceivers[friend] = 0;

    for (let j = 0; j < friends.length; j++) {
      if (friend === friends[j]) continue;
      giftRecords[friend][friends[j]] = 0;
    }
  }

  gifts.map((gift) => {
    const [giver, receiver] = gift.split(" ");

    // 선물 준 내역 계산하기
    giftRecords[giver][receiver] += 1;

    // 선물 지수 계산하기
    giftScores[giver] += 1;
    giftScores[receiver] -= 1;
  });

  // 선물내역, 선물지수로 다음달에 선물을 받는 사람 계산하기
  for (let i = 0; i < friends.length - 1; i++) {
    for (let j = i + 1; j < friends.length; j++) {
      const friendA = friends[i];
      const friendB = friends[j];

      const friendAToFriendB = giftRecords[friendA][friendB];
      const friendBToFriendA = giftRecords[friendB][friendA];

      const friendAGiftScore = giftScores[friendA];
      const friendBGiftScore = giftScores[friendB];

      if (friendAToFriendB === friendBToFriendA) {
        if (friendAGiftScore === friendBGiftScore) {
          continue;
        }
        friendAGiftScore > friendBGiftScore
          ? (nextMonthReceivers[friendA] += 1)
          : (nextMonthReceivers[friendB] += 1);
      } else {
        friendAToFriendB > friendBToFriendA
          ? (nextMonthReceivers[friendA] += 1)
          : (nextMonthReceivers[friendB] += 1);
      }
    }
  }

  const counts = Object.values(nextMonthReceivers);
  return Math.max(...counts);
}

비교

#1월에 작성한 코드

선물 지수와 주고받은 선물 내역을 동시에 관리하며, 반복문 내에서 조건문을 통해 최종 결과를 계산

  • giftCountlist라는 변수명을 사용하여 선물 지수와 선물 현황을 관리
  • 초기화 시 giftCount 객체를 사용하여 선물 지수와 선물 내역을 모두 관리
  • 하나의 반복문에서 많은 작업을 수행하여 코드가 비교적 짧고 간결하지만, 가독성이 다소 떨어질 수 있음
  • 새로운 요구 사항을 추가할 때, 기존 코드의 구조를 변경해야 할 가능성이 높음

#7월에 작성한 코드

선물 지수와 주고받은 선물 내역을 별도로 관리하여 더 명확한 구조를 유지. 최종 결과 계산을 별도의 반복문에서 수행.

  • giftRecords, giftScores, nextMonthReceivers와 같이 더 명확한 이름을 사용
  • 여러 반복문으로 작업을 분리하여 코드의 각 부분이 무엇을 하는지 더 명확히 알 수 있음
  • 각 작업이 분리되어 있어 디버깅과 테스트가 더 쉬우며 새로운 요구 사항을 추가할 때, 코드의 구조를 크게 변경하지 않고도 확장이 가능

결론

두 풀이 방법 모두 같은 시간복잡도를 가지므로, 성능면에서는 큰 차이가 없음.

  • 1월에 작성한 코드는 하나의 반복문에서 많은 작업들을 수행하기 때문에 성능적으로 더 나음.
  • 7월에 작성한 코드는 가독성 및 유지보수 측면에서 더 나음.
This post is licensed under CC BY 4.0 by the author.