문제 출처
https://programmers.co.kr/learn/courses/30/lessons/68644
프로그래머스
> 코딩 테스트 연습
> 월간 코드 챌린지 시즌1
> 두 개 뽑아서 더하기
정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.
#1
numbers : [2, 1, 3, 4, 1]
result : [2, 3, 4, 5, 6, 7]
#2
numbers : [5, 0, 2, 7]
result : [2, 5, 7, 9, 12]
입출력 예 #1
function solution(numbers) {
// 입력 받은 배열 깊은 복사
// 원배열 numbers를 변형시키지 않고 문제를 해결하기 위함
const copyNumbers = [...numbers]
// 이중 for loop을 쓰면 문제가 바로 풀릴 거라고 생각했지만 for문을 많이 쓰는 것은 지양해야 한다고 생각해서 재귀를 선택
function sumArrayFunc(numbers) {
// 일단, 나의 알고리즘은 배열에서 크기가 2인 부분집합을 모두 골라내어 더하는 것
// 1. 더한 값을 중복에 상관없이 그냥 새로운 배열에 넣는다.
// 2. 중복을 제거하고 오름차순으로 정렬한다.
// 배열의 무조건 첫번째 원소이다.
let leftPivot = 0
// 첫번째 원소와 더해지는 값이다.
let rightPivot = leftPivot + 1
// 일단 더한 값을 모두 중복, 오름차순에 상관 없이 모두 넣을 배열
let tempReturnValue = []
// 배열을 앞의 원소를 하나씩 제거하면서 재귀가 진행되는데 계속 잘려나가서 크기가 2가 되면 자를 수 있지만 나의 알고리즘에 위배 되기 때문에
// 2개가 되면 그 2개를 합하고 배열에 넣고 재귀를 끝낸다.
if(numbers.length === 2) {
return [...tempReturnValue, numbers[leftPivot] + numbers[rightPivot]]
}
// 재귀가 진행중인 코드
// 앞의 값은 고정이며, 오른쪽 인덱스 값이 1씩 증가하여 더하고, 오른쪽 피봇이 제일 끝에가면 for loop은 종료
for(let i = 0; i < numbers.length - 1; i++) {
tempReturnValue = [...tempReturnValue, numbers[leftPivot] + numbers[rightPivot]]
rightPivot++
}
// 배열의 앞 원소 1개 제거
numbers.splice(0, 1)
// 배열 재귀
return [...tempReturnValue, [...sumArrayFunc(numbers)]]
}
// 재귀 함수를 실행시키고 결과값을 저장
let returnValue = sumArrayFunc(copyNumbers)
// 배열의 중첩이 되었는데 중첩배열을 제거하고 깊이가 1인 일반배열로 변환
const flatArrayFunc = (arr, depth) => {
return arr.flat(depth)
}
returnValue = flatArrayFunc(returnValue, Infinity)
// set을 이용하여 중복제거 (set은 집합이다. (집합은 중복 허용X -> 중학교 수학개념))
const set = new Set(returnValue)
// 중복을 제거한 것을 다시 배열에 대입(선언)
let answer = [...set]
// 오름차순으로 정렬 후 반환
return answer.sort((a, b) => a - b)
}