스택(Stack)과 큐(Queue) - 올바른 괄호/주식가격/다리를 지나는 트럭/프로세스
스택(Stack)과 큐(Queue) - 올바른 괄호/주식가격/다리를 지나는 트럭/프로세스
스택 (LIFO, pop & push)
1. 올바른 괄호
스택(Stack) 자료구조를 사용하여 괄호 문자열이 올바른지 판별하는 문제
풀이 전략
- 괄호를 저장하기 위해 스택 사용
- 문자열 순회
- 여는 괄호인 경우 스택에 추가
- 닫는 괄호인 경우
- 스택이 비어 있다면, false 반환
- 스택에 괄호가 있다면 가장 최근에 추가된 여는 괄호를 제거(pop)하여 짝을 맞춤
- 최종 스택 상태 확인하여 값 반환
알고리즘 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function solution(s) {
// 1. 스택 초기화
const stack = [];
// 2. 문자열 순회
for (let char of s) {
// 여는 괄호인 경우 스택에 push
if (char === "(") {
stack.push(char);
// 닫는 괄호인 경우
} else {
// 스택이 비어 있다면, false 반환
if (stack.length === 0) {
return false;
}
// 스택에 괄호가 있다면 최근 여는 괄호 pop
stack.pop();
}
}
// 3. 최종 스택 상태 확인하여 값 반환
return stack.length === 0;
}
2. 주식가격
스택을 사용하여 가격이 떨어지는 시점을 효율적으로 계산하는 문제
풀이 전략
- 주식 가격을 확인하면서 현재 가격이 이전 가격보다 작다면 스택에 저장된 인덱스를 이용해 기간을 계산한다.
- 가격이 떨어지는 시점을 빠르게 계산하며, 모든 주식 가격에 대해 마지막까지 남아 있는 스택을 처리한다.
알고리즘 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function solution(prices) {
const result = Array(n).fill(0); // 결과 배열
const stack = []; // 가격의 인덱스를 저장할 스택
const n = prices.length;
for (let i = 0; i < n; i++) {
// 현재 가격이 스택의 마지막 가격보다 낮다면
while (stack.length > 0 && prices[stack[stack.length - 1]] > prices[i]) {
const top = stack.pop(); // 스택에서 인덱스를 꺼낸다
result[top] = i - top; // 현재 인덱스와의 차이를 결과로 저장
}
stack.push(i); // 현재 인덱스를 스택에 추가
}
// 스택에 남아있는 인덱스 처리 (끝까지 가격이 떨어지지 않은 경우)
while (stack.length > 0) {
const top = stack.pop();
result[top] = n - top - 1; // 끝까지 유지된 기간 계산
}
return result;
}
큐(FIFO, shift & push)
1. 다리를 지나는 트럭
큐(Queue) 구조를 활용하여 다리 위를 건너는 트럭의 상태를 시뮬레이션하며 해결하는 문제
풀이 전략
- 다리 상태를 큐로 표현
- 다리는
bridge_length
만큼의 길이를 가지므로, 다리 위에 있는 트럭들을 큐에 저장한다. - 트럭이 다리에 올라오면
bridge_length
동안 큐에 머문다.
- 다리는
- 다리 위 무게 관리
- 다리 위의 트럭 총 무게를 추적하여, 추가적인 트럭이 올라올 수 있는지 판단한다.
- 시뮬레이션 진행
- 다리 위의 트럭들을 한 칸씩 전진
- 다리를 지나간 트럭은 큐에서 제거
- 다리의 현재 무게를 확인하여 다음 트럭이 올라갈 수 있으면 큐에 추가
- 모든 트럭이 다리를 건넌 뒤 종료
알고리즘 풀이
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
function solution(bridge_length, weight, truck_weights) {
let time = 0; // 경과 시간
let bridge = Array(bridge_length).fill(0); // 다리를 큐로 표현
let currentWeight = 0; // 다리 위의 현재 무게
while (truck_weights.length > 0 || currentWeight > 0) {
time++;
// 다리의 첫 번째 칸에서 트럭 제거
currentWeight -= bridge.shift();
// 다음 트럭을 다리에 올릴 수 있는지 확인
if (
truck_weights.length > 0 &&
currentWeight + truck_weights[0] <= weight
) {
const truck = truck_weights.shift();
bridge.push(truck); // 트럭이 다리 위에 올라감
currentWeight += truck;
} else {
// 다리가 꽉 차 있으면 0을 추가 (빈 칸 유지)
bridge.push(0);
}
}
return time;
}
2. 프로세스
큐(Queue)를 활용하여 프로세스 우선순위에 따라 프로세스를 처리하고, 특정 프로세스의 실행 순서를 찾는 문제다. 큐와 우선순위를 고려한 시뮬레이션으로 해결하는 문제
풀이 전략
- 큐 구조로 프로세스 관리
- 각 프로세스의 중요도와 인덱스를 함께 큐에 저장
- 배열 메서드 shift와 push를 활용하여 큐 동작 구현
- 우선순위 확인
- 큐의 맨 앞 프로세스를 꺼내고 남아있는 큐와 우선순위 비교(shift)
- 높은 우선순위가 있다면 다시 큐의 맨뒤로 보냄(push)
- 프로세스 실행
- 높은 우선순위가 없다면 해당 프로세스를 실행
- 실행된 프로세스가 목표 프로세스라면 현재 실행 순서 반환
알고리즘 풀이
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
function solution(priorities, location) {
// 1. 큐 구조로 프로세스 관리
let queue = priorities.map((priority, index) => ({ priority, index })); // // 큐에 인덱스와 중요도 저장
let count = 0; // 실행 순서
// 2. 우선순위 확인
while (queue.length > 0) {
// 큐에서 첫번째 프로세스 꺼냄: shift()
let current = queue.shift();
// 우선순위가 더 높은 프로세스가 있으면
if (queue.some((process) => process.priority > current.priority)) {
queue.push(current); // 큐의 맨뒤로 보냄(push)
// 높은 우선 순위가 없다면
} else {
count++; // 현재 프로세스 실행
// 실행된 프로세스가 목표 프로세스일 경우 실행 순서 반환
if (current.index === location) {
return count;
}
}
}
return count;
}
This post is licensed under CC BY 4.0 by the author.