[프로그래머스] 삼총사 (Javascript)

2025. 2. 7. 10:30·Algorithm/프로그래머스 LV1

문제

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

요구사항
한국중학교에 다니는 학생들은 각자 정수 번호를 갖고 있습니다. 이 학교 학생 3명의 정수 번호를 더했을 때 0이 되면 3명의 학생은 삼총사라고 합니다. 예를 들어, 5명의 학생이 있고, 각각의 정수 번호가 순서대로 -2, 3, 0, 2, -5일 때, 첫 번째, 세 번째, 네 번째 학생의 정수 번호를 더하면 0이므로 세 학생은 삼총사입니다. 또한, 두 번째, 네 번째, 다섯 번째 학생의 정수 번호를 더해도 0이므로 세 학생도 삼총사입니다. 따라서 이 경우 한국중학교에서는 두 가지 방법으로 삼총사를 만들 수 있습니다.
한국중학교 학생들의 번호를 나타내는 정수 배열 number가 매개변수로 주어질 때, 학생들 중 삼총사를 만들 수 있는 방법의 수를 return 하도록 solution 함수를 완성하세요.

제한조건
·  3 ≤ number의 길이 ≤ 13
·  -1,000 ≤ number의 각 원소 ≤ 1,000
·  서로 다른 학생의 정수 번호가 같을 수 있습니다.

입출력
number result
[-2, 3, 0, 2, -5] 2
[-3, -2, -1, 0, 1, 2, 3] 5
[-1, 1, -1, 1] 0

 

내가 생각한 로직

처음에 생각한 로직

1. reduce 메서드로 배열의 전체 합을 구한다.

2. 전체 합에서 (배열의 전체 길이 - 3)개의 요소들의 합을 뺐을 때, 0이 되는 순간을 구한다.

3. count 변수를 만들어서 그 순간마다 count에 1을 더한다.

 

🚨 배열의 길이가 정해져있는 것이 아니기 때문에, 배열의 길이마다 숫자를 더해줘야 하는 방법을 고려해야 한다.

 

두 번째로 생각한 로직

1. for문을 3개 이용해서 배열의 요소에 3개까지 접근하게 만들기

2. i < j < k일 때 3개 숫자의 합을 구한다. (중복되는 경우를 제거하기 위해)

3. count 변수를 만들어서 합이 0일 때 count에 1을 더한다.

 

반복문을 이렇게 많이 써도 되나 싶어서 자신이 없었지만,

코드를 작성해 본 결과, 테스트를 통과하였다.

 

 

내가 구현한 코드

01 전체 합에서 (배열의 전체 길이 - 3)개의 요소들의 합을 빼면 0일 때 구하기 ❌

function solution(number) {
    const sum = number.reduce((acc, cur) => acc + cur);
    let count = 0;
    
    for(let i = 0; i < number.length; i++) {
        for(let j = 0; j < number.length; j++) {
            if (i !== j && i < j) {
                let twoSum = number[i] + number[j];
                console.log(twoSum);
                if (sum - twoSum === 0) count += 1;
            }
        }
    }
    return count;
}

🚨 첫번째 예시만 보고 코드를 짜고 다른 예시들을 고려하지 않고 짰었다.

배열의 전체 길이를 5라고만 생각하고 짰기 때문에, 첫 번째 예시를 제외하고는 나머지가 통과할 수 없었다.

이 로직에서 벗어나 다시 본점으로 돌아갔다.

 

 

02 3개의 for문 이용하기 ✅

function solution(number) {
    let count = 0;
    
    for (let i = 0; i < number.length; i++) {
        for (let j = 0; j < number.length; j++) {
            for (let k = 0; k < number.length; k++) {
                if (i < j < k) {
                    if (number[i] + number[j] + number[k] === 0) count += 0;
                }
            }
        }
    }
    return count;
}

이 로직이 맞는 것 같은데 왜 안되는지 이유를 모르겠어서 한참을 들여다보고 있었다.

&&로 조건문을 작성하는게 익숙하지 않아서 그런가 대놓고 잘못된 조건식을 작성하고 있었다.

 

if (i < j < k)

이렇게 작성하니 작동할리가 없었다.

 

if (number[i] + number[j] + number[k] === 0) count += 0;

게다가 count에 1을 더해줘야 되는데 0을 더하고 있었다.

 

 

function solution(number) {
    let count = 0;
    
    for (let i = 0; i < number.length; i++) {
        for (let j = 0; j < number.length; j++) {
            for (let k = 0; k < number.length; k++) {
                if (i < j && j < k) {
                    if (number[i] + number[j] + number[k] === 0) count += 1;
                }
            }
        }
    }
    return count;
}

조건식을 논리합 연산자(&&)로 수정해주고 count에 1을 더하는 로직으로 코드를 바꾸면 정상적으로 작동한다.

 

 

다른 해결방법

사용한 도구: combination 함수 제작, 재귀 함수 이용

function solution(number) {
    let result = 0;

    const combination = (current, start) => {
        if (current.length === 3) {
            result += current.reduce((acc, cur) => acc + cur, 0) === 0 ? 1 : 0;
            return;
        }

        for (let i = start; i < number.length; i++) {
            combination([...current, number[i]], i + 1);
        }
    }
    combination([], 0);
    return result;
}

 

const combination = (current, start) => {
  if (current.length === 3) {
    result += current.reduce((acc, cur) => acc + cur, 0) === 0 ? 1 : 0;
    return;
  }

  for (let i = start; i < number.length; i++) {
    combination([...current, number[i]], i + 1);
  }
};

 

배열의 길이가 3일 때 배열의 전체 합을 구하고, 합이 0이면 1을, 0이 아니면 0을 반환하는 함수를 제작하였다.

combination 함수로 들어가는 인자는 current와 start가 있다.

current = 현재까지 선택된 숫자 리스트

start = 탐색을 시작할 인덱스 (중복 선택 방지)

 

for (let i = start; i < number.length; i++) {
    combination([...current, number[i]], i + 1);
}
[]
├── [-2] (i = 0)
│   ├── [-2, 3] (i = 1)
│   │   ├── [-2, 3, 0] → 합: 1 (X)
│   │   ├── [-2, 3, 2] → 합: 3 (X)
│   │   ├── [-2, 3, -5] → 합: -4 (X)
│   ├── [-2, 0] (i = 2)
│   │   ├── [-2, 0, 2] → 합: 0 ✅ (result += 1)
│   │   ├── [-2, 0, -5] → 합: -7 (X)
│   ├── [-2, 2] (i = 3)
│   │   ├── [-2, 2, -5] → 합: -5 (X)
├── [3] (i = 1)
│   ├── [3, 0] (i = 2)
│   │   ├── [3, 0, 2] → 합: 5 (X)
│   │   ├── [3, 0, -5] → 합: -2 (X)
│   ├── [3, 2] (i = 3)
│   │   ├── [3, 2, -5] → 합: 0 ✅ (result += 1)
├── [0] (i = 2)
│   ├── [0, 2] (i = 3)
│   │   ├── [0, 2, -5] → 합: -3 (X)

재귀 호출의 흐름은 다음과 같다.

재귀 함수를 이용해서 배열의 길이가 3인 경우를 모두 찾은 뒤, 합이 0인 경우를 확인한다.

 

나는 함수 내에서 또 다른 함수를 제작할 생각을 하지도 못했고, 재귀 함수를 사용하는 방법도 몰랐다,

재귀 함수 때문에 이 코드를 이해하는데도 많은 시간이 걸렸다..

 

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'Algorithm > 프로그래머스 LV1' 카테고리의 다른 글

[프로그래머스] 시저 암호 (Javascript)  (1) 2025.02.11
[프로그래머스] 최소직사각형 (Javascript)  (0) 2025.02.10
[프로그래머스] 3진법 뒤집기 (Javascript)  (0) 2025.02.06
[프로그래머스] 이상한 문자 만들기 (Javascript)  (0) 2025.02.05
[프로그래머스] 예산 (Javascript)  (0) 2025.02.04
'Algorithm/프로그래머스 LV1' 카테고리의 다른 글
  • [프로그래머스] 시저 암호 (Javascript)
  • [프로그래머스] 최소직사각형 (Javascript)
  • [프로그래머스] 3진법 뒤집기 (Javascript)
  • [프로그래머스] 이상한 문자 만들기 (Javascript)
집으로 감자
집으로 감자
Hello World
  • 집으로 감자
    Potato to Home
    집으로 감자
  • 전체
    오늘
    어제
  • 링크

    • Github
    • 분류 전체보기
      • Front-end
        • TIL
        • Javascript
        • Typescript
        • React
        • Next.js
        • CSS
        • 라이브러리
      • Algorithm
        • 프로그래머스: 기초 트레이닝
        • 프로그래머스 LV1
      • TroubleShooting
      • Problem & Solution
      • Project
      • Programing Knowledge
        • 개발 용어
        • CS
        • 운영체제
        • 자료구조
        • 데이터 베이스
  • 태그

    JavaScript
    Til
    http
    회고
    코딩테스트
    프로그래머스
    styledcomponent
    반응형웹
    tanstackquery
    CSS
    문제해결
    react
    개발용어
    트러블슈팅
    실행컨텍스트
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
집으로 감자
[프로그래머스] 삼총사 (Javascript)
상단으로

티스토리툴바