티스토리 뷰
https://www.acmicpc.net/problem/12847
12847번: 꿀 아르바이트
월세를 내기 바로 전 날 까지 인 n (1 ≤ n ≤ 100,000) 일과 일을 할 수 있는 날 m (0 ≤ m ≤ n) 일이 주어진다. 그 다음 줄 에는 1일부터 n일 까지 일급 Ti가 순서대로 주어진다. (0 < Ti ≤ 1,000,000)
www.acmicpc.net
🤔 해결방법
1. 초기값 = 처음부터 m개의 합
2. 슬라이딩 윈도우로 앞에 하나 빼고 뒤에 하나 더하기
3. 그 값을 profit에 push
4. 2,3번 반복
5. profit에서 가장 큰 값 출력
🔑 풀이
const input = require("fs")
// .readFileSync("/dev/stdin")
.readFileSync(__dirname + "/input.txt")
.toString()
.trim()
.split("\n");
const [n, m] = input[0].split(" ").map(Number);
const t = input[1].split(" ").map(Number); // 일급
let profit = []; // 얻을 수 있는 이익
let value = 0;
// 초기값
for (let i = 0; i < m; i++) {
value += t[i];
}
profit.push(value);
for (let i = 0; i < n; i++) {
if (i + m < n) {
value -= t[i]; // 앞의 수 빼기
value += t[i + m]; // 뒤의 수 더하기
profit.push(value);
}
}
console.log(Math.max(...profit));
슬라이딩 윈도우를 처음 알게 되었다.
슬라이딩 윈도우는 투포인터와 개념이 비슷한데, 투포인터는 구간 넓이가 유동적으로 변하지만 슬라이딩 윈도우는 구간의 넓이가 항상 고정된다는 차이가 있다.
따라서 for문에서 맨 앞의 수는 빼고 뒤의 수는 하나 더해주면서 윈도우 크기를 유지하며 풀어야 한다.
https://www.acmicpc.net/problem/21921
21921번: 블로그
첫째 줄에 $X$일 동안 가장 많이 들어온 방문자 수를 출력한다. 만약 최대 방문자 수가 0명이라면 SAD를 출력한다. 만약 최대 방문자 수가 0명이 아닌 경우 둘째 줄에 기간이 몇 개 있는지 출력한다
www.acmicpc.net
🤔 해결방법
1. 초기값 = 처음부터 x개의 합
2. 슬라이딩 윈도우로 앞에 하나 빼고 뒤에 하나 더하기
3. 그 값을 visitNumbers에 push
4. 2,3번 반복
5-1. visitNumbers에서 가장 큰 값이 0이면 SAD
5-2. 가장 큰 값이 0이 아니면 최대값과 개수 출력
🔑 풀이
const input = require("fs")
// .readFileSync("/dev/stdin")
.readFileSync(__dirname + "/input.txt")
.toString()
.trim()
.split("\n");
const [n, x] = input[0].split(" ").map(Number);
const visit = input[1].split(" ").map(Number); // 방문자 수
let visitNumbers = []; // x일 동안의 방문자 수 합
let value = 0;
// 초기값
for (let i = 0; i < x; i++) {
value += visit[i];
}
visitNumbers.push(value);
for (let i = 0; i < n; i++) {
if (i + x < n) {
value -= visit[i]; // 앞의 수 빼기
value += visit[i + x]; // 뒤의 수 더하기
visitNumbers.push(value);
}
}
let max = Math.max(...visitNumbers); // 최대값
if (max === 0) {
console.log("SAD");
} else {
let count = visitNumbers.reduce((cnt, e) => cnt + (max === e), 0); //최대값 개수
console.log(max + "\n" + count);
}
꿀 아르바이트 문제와 거의 흡사한 방식이라 슬라이딩 윈도우를 사용하여 쉽게 풀 수 있었다.
https://www.acmicpc.net/problem/12891
12891번: DNA 비밀번호
평소에 문자열을 가지고 노는 것을 좋아하는 민호는 DNA 문자열을 알게 되었다. DNA 문자열은 모든 문자열에 등장하는 문자가 {‘A’, ‘C’, ‘G’, ‘T’} 인 문자열을 말한다. 예를 들어 “ACKA”
www.acmicpc.net
🤔 해결방법
1. DNA 문자열 (A, C, G, T)과 각 DNA 문자열의 개수를 객체로 만들기
2. 각 DNA 문자열의 출현 횟수를 기록할 strCount 객체 초기화
3. 첫 번째 슬라이딩 윈도우를 초기화하고, 해당 윈도우 내에서 각 DNA 문자열이 몇 번 출현하는지 카운트
4. 만약 strCount 객체 내의 각 DNA 문자열의 출현 횟수가 dna 객체 내의 각 DNA 문자열의 개수보다 많거나 같다면, 답의 개수를 하나 증가
5. 슬라이딩 윈도우를 오른쪽으로 한 칸씩 이동시키며 위의 과정을 반복
이때, 윈도우에서 빠지는 요소의 카운트를 감소시키고, 윈도우에 들어오는 요소의 카운트를 증가시킵니다.
6. 답의 개수 출력
🔑 풀이
const input = require("fs")
// .readFileSync("/dev/stdin")
.readFileSync(__dirname + "/input.txt")
.toString()
.trim()
.split("\n");
const str = input[1];
const [strLength, subStrLength] = input[0].split(" ").map(Number);
const dnaStr = ["A", "C", "G", "T"];
const dnaStrNum = input[2].split(" ").map(Number);
const dna = dnaStr.reduce((obj, key, index) => {
obj[key] = dnaStrNum[index];
return obj;
}, {});
let answer = 0;
let strCount = { A: 0, C: 0, G: 0, T: 0 }; // 부분 문자열 내에 각 DNA 문자열이 몇 번 나타나는지
for (let i = 0; i < subStrLength; i++) {
// 첫 번째 윈도우 초기화
if (str[i] in dna) strCount[str[i]]++;
}
// strCount가 dna의 각 요소보다 크거나 같다면 answer +1
if (Object.keys(dna).every((key) => dna[key] <= strCount[key])) answer++;
for (let i = subStrLength; i < strLength; i++) {
// 슬라이딩 윈도우
strCount[str[i - subStrLength]]--; // 윈도우에서 빠지는 요소 감소
strCount[str[i]]++; // 윈도우에 들어오는 요소 증가
if (Object.keys(dna).every((key) => dna[key] <= strCount[key])) answer++;
}
console.log(answer);
// 시간초과
// function solution(str, dna) {
// for (let i = 0; i < str.length - subStrLength; i++) {
// let subStr = str.slice(i, i + Number(subStrLength)); // 부분문자열
// // 각 문자 개수 세기
// let strCount = { A: 0, C: 0, G: 0, T: 0 };
// for (let s of subStr) {
// if (s in dna) strCount[s]++;
// }
// // 조건 만족하면 answer++
// if (Object.keys(dna).every((key) => dna[key] <= strCount[key])) {
// answer++;
// }
// }
// return answer;
// }
// console.log(solution(str, dna));
처음에 슬라이딩 윈도우를 모를 때 그냥 이중for문으로 풀었던 것은 시간초과가 떴었다.
대충 이 3문제 정도 푸니 슬라이딩 윈도우 풀이 방법 감이 잡힌 것 같다!!
'JS-algorithm > BOJ' 카테고리의 다른 글
[백준] 피보나치수 2, 피보나치수 3, 파도반 수열 (javascript) (0) | 2024.01.03 |
---|---|
[백준] 전화 요금 (javascript) (0) | 2023.10.19 |
[백준] 평범한 배낭 (javascript) (0) | 2023.08.28 |