이번 글에서는 숫자로 이루어진 두 개의 배열을 인수로 받는 JavaScript 함수를 작성해 보겠습니다.
이 함수는 두 배열을 하나로 합친 뒤 임의의 순서로 재배열했을 때, 연속된 수열(연속적인 시퀀스)을 만들 수 있으면 true를, 만들 수 없으면 false를 반환해야 합니다.
예를 들어, 입력 배열이 다음과 같다고 가정해 보겠습니다.
const arr1 = [4, 6, 2, 9, 3];
const arr2 = [1, 5, 8, 7];
두 배열을 합치면 [4, 6, 2, 9, 3, 1, 5, 8, 7]이 되고, 이를 정렬하면 [1, 2, 3, 4, 5, 6, 7, 8, 9]로 1부터 9까지 빠짐없이 이어지는 연속된 수열입니다. 따라서 출력 결과는 true여야 합니다.
문제 해결 접근 방식
이 문제는 다음 세 단계로 해결할 수 있습니다.
1. 두 배열을 하나로 합치기
전개 연산자(spread operator)를 사용해 두 배열의 모든 요소를 새로운 배열에 담습니다.
2. 배열을 오름차순으로 정렬하기
sort() 메서드에 비교 함수 (a, b) => a - b를 전달하여 숫자 크기순으로 정렬합니다. 비교 함수를 생략하면 문자열 기준으로 정렬되므로 반드시 명시해야 합니다.
3. 인접 요소 간의 차이가 일정한지 검사하기
정렬된 배열에서 첫 번째 요소와 두 번째 요소의 차이를 공차(common difference)로 저장한 뒤, 나머지 인접 요소들의 차이가 이 공차와 같은지 순회하며 확인합니다. 중간에 하나라도 다르면 즉시 false를 반환합니다.
예제 코드
위 접근 방식을 구현한 전체 코드는 다음과 같습니다.
const arr1 = [4, 6, 2, 9, 3];
const arr2 = [1, 5, 8, 7];
const canFormSequence = (arr1, arr2) => {
// 두 배열을 하나로 합침
const combined = [...arr1, ...arr2];
// 요소가 2개 미만이면 항상 수열로 볼 수 있음
if (combined.length < 2) {
return true;
}
// 오름차순 정렬
combined.sort((a, b) => a - b);
// 첫 두 요소의 차이를 공차로 설정
const commonDifference = combined[0] - combined[1];
// 인접 요소 간 차이가 공차와 일치하는지 검사
for (let i = 1; i < combined.length - 1; i++) {
if (combined[i] - combined[i + 1] === commonDifference) {
continue;
}
return false;
}
return true;
};
console.log(canFormSequence(arr1, arr2));
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
true
동작 원리 정리
배열 [4, 6, 2, 9, 3]과 [1, 5, 8, 7]을 합쳐 정렬하면 [1, 2, 3, 4, 5, 6, 7, 8, 9]가 되고, 인접한 모든 요소의 차이가 일정하게 유지됩니다. 따라서 최종적으로 true가 반환됩니다.
반대로 예를 들어 arr1 = [4, 6, 2, 9], arr2 = [1, 5, 8]처럼 수열 중간에 빠진 숫자가 있다면 정렬 후 차이가 일정하지 않아 false가 반환됩니다.
이 알고리즘은 정렬에 O(n log n)의 시간 복잡도를 가지며, 이후 순회 과정은 O(n)이므로 전체적으로 효율적인 편입니다. 참고로 위 코드는 인접 요소 간 차이가 일정한 등차수열인지를 검사하는 방식이므로, 반드시 1씩 증가하는 연속 정수만 허용하고 싶다면 공차가 -1(오름차순 기준)인지 추가로 확인하면 됩니다.