일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 스나이퍼팩토리
- App Runner
- 인사이드아웃
- IT개발캠프
- 리액트
- 해시
- 스레드
- 프로세스
- react
- 네트워크
- 유데미
- 타입스크립트
- 자바스크립트
- react-query
- 프로젝트캠프
- typescript
- html
- Algorithm
- 메모리
- BFS
- cs #네트워크
- CS
- ip
- javascript
- 웅진씽크빅
- 프로그래머스
- React.js
- 개발자부트캠프
- #프로젝트캠프 #프로젝트캠프후기 #유데미 #스나이퍼팩토리 #웅진씽크빅 #인사이드아웃 #IT개발캠프 #개발자부트캠프 #리액트 #react #부트캠프 #리액트캠프
- 알고리즘
- Today
- Total
Bin's Blog
[프로그래머스] Level2 - 연속된 부분 수열의 합(Javascript) 본문
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
▶ 문제 요약
1. 기존 수열에서 임의의 두 인덱스의 원소와 그 사이의 원소를 모두 포함하는 부분 수열이어야 한다.
2. 부분 수열의 합은 k이다.
3. 합이 k인 부분 수열이 여러 개인 경우 길이가 짧은 수열을 찾는다.
4. 길이가 짧은 수열이 여러 개인 경우 앞쪽(시작 인덱스가 작은)에 나오는 수열을 찾는다.
▶ 실패 코드
function solution(sequence, k) {
let answer = [];
let temp = [];
let sum = 0;
for (let i = 0; i < sequence.length; i++) {
temp.push([sequence[i], i]);
sum += sequence[i];
while (sum > k) {
sum -= temp[0][0];
temp.shift();
}
if (sum === k) {
answer.push([temp[0][1], temp[temp.length-1][1], temp.length]);
sum -= temp[0][0];
temp.shift();
}
}
answer.sort((a, b) => a[2] - b[2]);
let result = answer[0];
return [result[0], result[1]];
}
▶ 실패 이유
1. 일단 위 코드의 시간복잡도를 보면 배열을 한 번 훑는 작업의 시간 복잡도는 O(N)이다.
2. answer을 정렬하는 작업에서 sort()함수 쓰는데 퀵소트를 기반을 하기 때문에 평균복잡도 n log n 복잡도를 가진다. 그러나 최악의 경우 n^2가 된다.
3. shift() 연산은 O(n)을 가지기 때문에 while 루프 내부의 시간 복잡도는 실제로 O(n ^2)가 된다.
4. 따라서 주어진 배열의 크기가 1000000이면 시간초과가 난다.
▶ 정답 코드
function solution(sequence, k) {
let answer = [];
let start = 0, end = 0, sum = 0;
let minLen = Infinity;
// end가 주어진 배열의 크기보다 작거나 같을 때까지 돌면서
while (end <= sequence.length) {
// 합이 k보다 작으면
if (sum < k) {
// 배열 중에서 end에 해당하는 값을 더해주고 후위증가한다.
sum += sequence[end++];
// 만약 합이 k보다 크면
} else (sum > k) {
// 배열 중에서 start에 해당하는 값을 빼주고 후위증가한다.
sum -= sequence[start++];
// 같으면
} else (sum === k) {
// 길이가 짧은 수열을 찾기
if (end - start < minLen) {
// 가장 짧은 수열 업데이트
minLength = end - start;
// 결과값 담기
result = [start, end-1];
}
// 배열 중에서 start에 해당하는 값을 빼주고 후위증가한다.
sum -= sequence[start++];
}
}
return result
}
▶ 풀이 과정
1. 슬라이딩 윈도우 알고리즘을 활용했다. 배열이나 문자열 같은 선형 구조에서 요소의 일정 범위값을 비교할때 이용하면 유용한 방법이다. 투 포인터 패턴과 유사하다. 왼쪽 포인터와 오른쪽 포인터를 조정하는 방식으로 구현하는데 배열을 고정시키기 때문에 효율적이다. 주로 최대/최소값, 평균값 또는 해당 범위 내에서 특정 조건을 충족하는 값을 찾는 문제에 사용된다.
* 슬라이딩 윈도우 알고리즘 사용 일반적인 자바스크립트 구현 방법
let arr = [...]; // 주어진 배열
let windowSize = ...; // 윈도우 크기
let windowSum = 0; // 윈도우 내의 합
// 윈도우 초기화
for (let i = 0; i < windowSize; i++) {
windowSum += arr[i];
}
// 윈도우를 배열의 오른쪽으로 슬라이드
for (let i = windowSize; i < arr.length; i++) {
windowSum += arr[i] - arr[i - windowSize];
// 여기서 windowSum은 윈도우 내의 합을 나타냄
}
// 필요에 따라 이후에 windowSum을 이용해 처리
2. 코드 실행과정을 통해서 이해해보자.
- 초기 설정: start = 0, end = 0, sum = 0, minLength = Infinity, result = []
- sequence = [1, 1, 1, 2, 3, 4, 5]이고, k = 5.
- 첫 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행. sum = 1, end = 1
- 두 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행. sum = 2, end = 2
- 세 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행. sum = 3, end = 3
- 네 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행. sum = 5, end = 4
- 이제 sum === k이므로, if (end - start < minLength)를 확인. minLength는 무한대이므로, result = [start, end - 1]를 실행 result = [0, 3]
- 그리고 sum -= sequence[start++]를 실행. sum = 4, start = 1
- 다섯 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행. sum = 7, end = 5
- sum > k이므로, sum -= sequence[start++]를 실행. sum = 6, start = 2
- 여섯 번째 반복:
- sum > k이므로, sum -= sequence[start++]를 실행. sum = 5, start = 3
- 이제 sum === k이므로, if (end - start < minLength)를 확인. 그러나 end - start는 2이고 minLength는 4이므로, result는 변경돼서 result = [3, 4]
- 그리고 sum -= sequence[start++]를 실행합니다. sum = 3, start = 4
- 일곱 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행합니다. sum = 7, end = 6
- sum > k이므로, sum -= sequence[start++]를 실행합니다. sum = 4, start = 5
- 여덟 번째 반복:
- sum < k이므로, sum += sequence[end++]를 실행합니다. sum = 9, end = 7
- sum > k이므로, sum -= sequence[start++]를 실행합니다. sum = 5, start = 6
- 이제 sum === k이므로, if (end - start < minLength)를 확인합니다. 그러나 end - start는 1이고 minLength는 4이므로
- result는 변경되서 result = [6, 6]
'Algorithm' 카테고리의 다른 글
[프로그래머스] Level2 - 방금그곡(Javascript) (0) | 2023.05.13 |
---|---|
[프로그래머스] Level2 - 괄호 변환(Javascript) (0) | 2023.05.10 |
[프로그래머스] Level2 - 택배상자(Javascript) (0) | 2023.05.05 |
[프로그래머스] Level2 - 124 나라의 숫자(Javascript) (0) | 2023.05.05 |
[프로그래머스] Level2 - 삼각 달팽이(Javascript) (0) | 2023.05.04 |