시리즈: 알고리즘 (32개 글)
- 자바로 알고리즘 풀기
- [Java] 백준 10431 - 줄 세우기
- [Java & Node.js] 백준 9935 - 문자열 폭발
- [Node.js] 백준 22866 - 탑 보기
- [Java] 백준 4485 - 녹색 옷 입은 애가 젤다지?
- [Node.js] 백준 1283 - 단축키 지정
- [Java & Node.js] 백준 14469 - 소가 길을 건너간 이유 3
- [Java] 백준 8979 - 올림픽
- [Node.js] 백준 22866 - 탑 보기
- [Java] 백준 7568 - 덩치
- [Java] 백준 1244 - 스위치 켜고 끄기
- [Node.js] 백준 19941 - 햄버거 분배
- [Node.js] 백준 1254 - 팰린드롬 만들기
- [Java] 백준 2589 - 보물섬
- [Java] 백준 2309 - 일곱 난쟁이
- [Java] 백준 1789 - 수들의 합
- [Java] 백준 1987 - 알파벳
- [Node.js] [Rust] 백준 24460 - 특별상이라도 받고 싶어
- [Node.js] 백준 7576 - 탑 보기
- [Rust] 백준 1047 - 울타리 (N^4 브루트포스 + 그리디)
- [Node.js] 백준 9657 - 돌게임3
- [Rust] 백준 4963 - 섬의 개수
- [Node.js] 프로그래머스 - 모의고사 / 실패율
- [Rust] 백준 2667 - 단지번호붙이기
- [Node.js] 프로그래머스 - 방문 길이
- [Node.js] 프로그래머스 - 괄호 회전하기
- [Rust] 백준 1002 - 터렛
- [Node.js] 프로그래머스 - 크레인 인형뽑기 게임
- [Node.js] 프로그래머스 - 기능개발
- [Rust] 백준 13717 - 포켓몬 GO
- [JavaScript] 백준 1092 - 배
- [Rust] 백준 25329 - 학생별 통화 요금 계산
[Node.js] 백준 22866 - 탑 보기
이거 왜 어렵지?
진짜 왜 어렵지?
왜 시간초과지?
예시 입력:
6
10 4 2 8 11 7
예시 출력:
1 4
1 1
0
2 5
2 4
1 5
접근
그냥 양쪽 다 확인하자 -> 시간초과
스택 두 번 나눠서 따로 돌리자 -> 오잉… 왜 됨..?
O(N^2)과 O(N)이 되어벌인..
핵심
buildings: 각 건물의 높이 저장된 곳visibleCount: 각 건물에서 볼 수 있는 총 건물 개수closestBuilding: 가장 가까운 건물 번호
코드
const input = require("fs")
.readFileSync("/dev/stdin")
.toString()
.replace(/\r/g, "")
.trim()
.split("\n");
const N = parseInt(input[0]);
let buildings = input[1].split(" ").map(Number);
buildings = [0, ...buildings];
const visibleCount = Array(N + 1).fill(0);
const closestBuilding = Array(N + 1).fill(Infinity);
const st = []; // 스택
// 왼쪽에서 오른쪽으로 순회 (1번 건물부터 N번 건물까지)
for (let i = 1; i <= N; i++) {
const currentHeight = buildings[i];
while (st.length > 0 && st[st.length - 1][1] <= currentHeight) {
st.pop();
}
if (st.length > 0) {
visibleCount[i] += st.length;
const [leftBuildingIdx, leftBuildingHeight] = st[st.length - 1];
if (Math.abs(i - leftBuildingIdx) < Math.abs(i - closestBuilding[i])) {
closestBuilding[i] = leftBuildingIdx;
} else if (
Math.abs(i - leftBuildingIdx) === Math.abs(i - closestBuilding[i])
) {
closestBuilding[i] = Math.min(closestBuilding[i], leftBuildingIdx);
}
}
st.push([i, currentHeight]);
}
// 스택 초기화
st.length = 0;
// 오른쪽에서 왼쪽으로 순회 (N번 건물부터 1번 건물까지)
for (let i = N; i >= 1; i--) {
const currentHeight = buildings[i];
while (st.length > 0 && st[st.length - 1][1] <= currentHeight) {
st.pop();
}
if (st.length > 0) {
visibleCount[i] += st.length;
const [rightBuildingIdx, rightBuildingHeight] = st[st.length - 1];
if (Math.abs(i - rightBuildingIdx) < Math.abs(i - closestBuilding[i])) {
closestBuilding[i] = rightBuildingIdx;
} else if (
Math.abs(i - rightBuildingIdx) === Math.abs(i - closestBuilding[i])
) {
closestBuilding[i] = Math.min(closestBuilding[i], rightBuildingIdx);
}
}
st.push([i, currentHeight]);
}
let result = "";
for (let i = 1; i <= N; i++) {
result += visibleCount[i];
if (visibleCount[i] > 0) {
result += ` ${closestBuilding[i]}`;
}
result += "\n";
}
console.log(result.trim());
결론
가끔은 나눠서 처리하자.
그리고 스택을 돌리면서 나보다 큰 것만 남기고 남은 요소들이 보이는 개수!
한국어 공부를 잘 해야 하는 문제.
