가장 많이 받은 선물 비교
1월에 풀었던 문제를 다른 방법으로 다시 풀었고 작성한 코드를 비교한 글
https://school.programmers.co.kr/learn/courses/30/lessons/258712?language=javascript
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월에 작성한 코드
선물 지수와 주고받은 선물 내역을 동시에 관리하며, 반복문 내에서 조건문을 통해 최종 결과를 계산
giftCount
와list
라는 변수명을 사용하여 선물 지수와 선물 현황을 관리- 초기화 시 giftCount 객체를 사용하여 선물 지수와 선물 내역을 모두 관리
- 하나의 반복문에서 많은 작업을 수행하여 코드가 비교적 짧고 간결하지만, 가독성이 다소 떨어질 수 있음
- 새로운 요구 사항을 추가할 때, 기존 코드의 구조를 변경해야 할 가능성이 높음
#7월에 작성한 코드
선물 지수와 주고받은 선물 내역을 별도로 관리하여 더 명확한 구조를 유지. 최종 결과 계산을 별도의 반복문에서 수행.
giftRecords
,giftScores
,nextMonthReceivers
와 같이 더 명확한 이름을 사용- 여러 반복문으로 작업을 분리하여 코드의 각 부분이 무엇을 하는지 더 명확히 알 수 있음
- 각 작업이 분리되어 있어 디버깅과 테스트가 더 쉬우며 새로운 요구 사항을 추가할 때, 코드의 구조를 크게 변경하지 않고도 확장이 가능
결론
두 풀이 방법 모두 같은 시간복잡도를 가지므로, 성능면에서는 큰 차이가 없음.
- 1월에 작성한 코드는 하나의 반복문에서 많은 작업들을 수행하기 때문에 성능적으로 더 나음.
- 7월에 작성한 코드는 가독성 및 유지보수 측면에서 더 나음.
This post is licensed under CC BY 4.0 by the author.