728x90
분류
- 스택
문제
풀이
자신과 가까운 것부터 순차적으로 비교해봐야하므로 스택이 필요함을 알 수 있다.
모든 타워에 대해 조사해보아야 하므로 타워의 갯수 n개만큼 반복문을 돌아야 한다.
방법에는 2가지가 있는데, for문에서 i=0부터 n까지 앞부터 실행하는 것과,
i=n부터 0까지 뒤에서부터 실행하는 방법이 있다.
앞부터 실행하는 방법은, 이미 어떤 타워가 자신의 신호를 송신할지 결정된 타워들을 스택에 넣어두고,
결정을 해야하는 타워와 스택을 하나씩 비교해서, 현재 타워보다 높이가 낮으면 pop해간다.
1 ) 스택이 비어버리면, 자신 이전에 자신보다 큰 타워가 없어서 아무도 자신의 신호를 송신하지 못하므로 0이다
2 ) 자신보다 높은 타워가 발견되면, (스택을 이용해 가까운 순서대로 검사했으므로) 해당 타워의 인덱스가 답이된다.
여기서, 검사 중 자신보다 낮아서 pop되었다는 뜻은
그 다음 타워로 넘어가도 어쩌피 고려할 가치가 없다는 뜻이므로 신경쓸 필요가 없다.
뒤부터 실행하는 방법은, 반대로 뒤부터 검사하기 때문에
맨 뒤 인덱스 타워부터 답이 정해지지 않은 타워를 스택에 넣어두고, 답이 정해지면( i-- 왼쪽으로 가면서 자신보다 큰 타워가 등장할 경우) 답을 작성하고 pop한다.
모든 타워가 답이 정해져 스택이 empty이면, 해당인덱스의 타워를 스택에 넣고, 왼쪽으로 이동하여 다시수행한다.
코드
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
/**
* [문제설명]
* 탑은 모두 왼쪽 방향으로 레이저를 보냄
* 각 탑에서 발사한 레이저 신호를 어느 탑에서 수신하는지 알아내는 문제
*
* [문제풀이]
* 스택에 탑의 높이가 아닌 인덱스를 넣어야 함을 파악해 푸는 문제
* 항상 스택의 top에 있는 인덱스의 탑 높이가 낮아야 함 (자신보다 높은 탑 중 가장 왼쪽에 있는 탑이 신호 수신하기 때문)
* 1. (1 ~ n) 따라서 스택의 top에 있는 인덱스의 탑 높이가 현재 탑 높이와 같거나 낮다면 pop
* 1. (1 ~ n) 앞의 과정이 끝난 후 스택이 비어있지 않다면 top에 있는 인덱스가 현재 탑의 신호를 수신하는 탑임
* 2. (n ~ 1) 따라서 스택의 top에 있는 인덱스의 탑 높이가 현재 탑 높이보다 낮다면 현재 탑이 수신탑
*/
//1 ~ n 돌면서 수신탑 찾기
vector<int> transTop1(int n, vector<int> &num) {
stack<int> st;
vector<int> ans(n + 1, 0); //수신 탑 저장
for (int i = 1; i <= n; i++) {
while (!st.empty() && num[st.top()] <= num[i]) { //현재 탑 높이보다 st.top() 인덱스의 탑 높이가 같거나 낮다면 pop
st.pop();
}
if (!st.empty()) ans[i] = st.top(); //스택이 비어있지 않다면 스택의 top에 저장된 인덱스가 현재 탑의 신호 수신탑
st.push(i); //현재 탑 인덱스 스택에 push
}
return ans;
}
//n ~ 1 돌면서 수신탑 찾기
vector<int> transTop2(int n, vector<int> &num) {
stack<int> st;
vector<int> ans(n + 1, 0); //수신 탑 저장
for (int i = n; i >= 1; i--) {
while (!st.empty() && num[st.top()] < num[i]) { //현재 탑 높이보다 st.top() 인덱스의 탑 높이가 낮다면 현재 탑이 수신탑
ans[st.top()] = i;
st.pop(); //수신탑이 정해졌으므로 pop
}
st.push(i); //현재 탑 인덱스 스택에 push
}
return ans;
}
int main() {
int n;
//입력
cin >> n;
vector<int> num(n + 1, 0); //탑의 인덱스가 1부터 시작하므로 n+1 할당
for (int i = 1; i <= n; i++)
cin >> num[i];
//연산
//vector<int> ans = transTop1(n, num);
vector<int> ans = transTop2(n, num);
//출력
for (int i = 1; i <= n; i++) {
cout << ans[i] << ' ';
}
return 0;
}
pair를 이용하여 구하는 방법도 있다.
//2. 탑의 높이, 탑의 인덱스를 동시에 저장하는 pair stack사용
stack<pair<int, int>> s; // 탑의 높이, 몇번째 탑인지
vector<int> ans;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, num;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> num;
while (!s.empty()) {
if (s.top().first >= num) {
ans.push_back(s.top().second);
break;
}
s.pop(); // 나보다 큰거는 pop해버리면안됨 , 작은건 앞으로 고려 x라서 pop
}
if (s.empty()) { //스택 끝까지 다찾아봤는데 더큰 탑이 없엇음 - > 0개
ans.push_back(0);
}
s.push({num, i + 1}); // 지금 받은거 스택에 넣기
}
for (int i = 0; i < N; i++) {
cout << ans[i] << " ";
}
}
728x90
'Algorithm > BaekJoon' 카테고리의 다른 글
[20302] 민트초코 (0) | 2021.09.27 |
---|---|
[2841] 외계인의 기타 연주 (0) | 2021.09.27 |
[11723] 집합 (0) | 2021.09.23 |
[11000] 강의실 배정 (0) | 2021.09.23 |
[3613] Java vs C++ - Priority Queue에 string넣으면 (0) | 2021.09.18 |