Skip to content

Conversation

@Mingguriguri
Copy link
Collaborator

@Mingguriguri Mingguriguri commented May 24, 2025

🌱WIL

이번 한 주의 소감을 작성해주세요!

  • 이번 주에는 부트캠프나 갑작스럽게 잡힌 면접 준비로 코테 문제를 많이 풀지는 못했다. 그래도 발제&과제 문제를 풀면서 BFS의 기본 개념을 다시 되새길 수 있었다.
  • Java 로 풀이하는 연습을 하기 위해서 프로그래머스 고득점 kit의 스택/큐 문제를 마무리했다. 다리를 지나는 트럭이나 주식가격 문제 모두 생각의 전환이 필요했다. 0을 추가해놓는다던지 인덱스를 스택에 저장한다던지 등등..

🚀주간 목표 문제 수: 3개

푼 문제


프로그래머스 #42583. 다리를 지나는 트럭: 스택큐 / Level2

정리한 링크: (바로가기)

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 다리(큐)를 0으로 초기화한다 (bridge_length만큼)
  2. 시간(time)을 0으로 설정
  3. 반복문을 통해:
    • poll()로 트럭 또는 0을 제거, 하중 차감
    • 대기 트럭이 조건을 만족하면 진입, 하중 증가
    • 아니면 0 삽입
  4. 트럭이 모두 지나면 종료 (while 탈출 조건)
  5. 누적된 time을 반환

🚩제출한 코드

import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        
        Queue<Integer> bridge = new LinkedList<>();
        for (int i = 0; i < bridge_length; i++) {
            bridge.offer(0);    // 처음에 빈 칸으로 채워둔다.
        }
        
        int time = 0;    // 전체 경과 시간
        int current = 0;       // 다리 위 현재 무게 합
        int idx = 0;        // 다음에 보낼 트럭 인덱스
        
        while (idx < truck_weights.length || current > 0) {
            time++;
            // 1. 다리에서 한 칸 빠져나옴
            int left = bridge.poll();
            current -= left; // 빠져나간 게 0일수도 있고, 트럭일 수도 있음.
            
            // 2. 다음 트럭을 올릴 수 있으면 올리기, 아니면 빈 칸(0) 올리기
            if (idx < truck_weights.length && current + truck_weights[idx] <= weight) {
                bridge.offer(truck_weights[idx]);
                current += truck_weights[idx];
                idx++;
            }
            else {
                bridge.offer(0);
            }
        }
        return time;
    }
}

💡TIL

배운 점이 있다면 입력해주세요

  • 이 문제의 핵심은 다리를 큐처럼 생각하는 것이다. 다리 길이만큼의 칸을 유지하며 매 초마다 트럭이 1칸씩 이동한다고 생각하면 된다.
  • 다리에 빈 공간을 0으로 채워 넣는 발상이 인상 깊었다. 이후 유사한 문제도 비슷하게 짤 수 있을 것 같다.
  • 자바에서는 **Queue의 핵심 메서드인 offer(), poll(), peek()**의 사용법을 꼭 숙지해두자.

프로그래머스 #42584. 주식가격: 스택큐 / Level2

정리한 링크: (바로가기)

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  • prices.length만큼의 answer[] 배열 생성
  • 인덱스를 순회하면서:
    • 스택이 비지 않았고, 현재 가격이 이전 가격보다 낮으면
      • 유지 시간 계산: 현재 인덱스 - 이전 인덱스
      • answer[이전 인덱스] = 유지시간
  • 끝까지 떨어지지 않은 인덱스는 (마지막 인덱스 - 해당 인덱스)를 할당

🚩제출한 코드

import java.util.Stack;

public class Solution {
    public int[] solution(int[] prices) {
        int n = prices.length;
        int[] answer = new int[n];
        // 아직 가격이 떨어지지 않은 시점들의 인덱스를 담을 스택
        Stack<Integer> st = new Stack<>();

        for (int i = 0; i < n; i++) {
            // 지금 가격(prices[i])이 스택 위 시점의 가격보다 낮다면,
            // 그 시점의 가격은 i 시점에 떨어진 것이므로
            // answer[idx] = i - idx 로 구간 길이를 확정짓고 pop
            while (!st.isEmpty() && prices[st.peek()] > prices[i]) {
                int idx = st.pop();
                answer[idx] = i - idx;
            }
            // 현재 시점 i를 스택에 추가
            st.push(i);
        }

        // 마지막까지 가격이 떨어지지 않은 인덱스들은
        // 끝까지(마지막 인덱스 n-1) 버틴 시간이 (n-1) - idx
        while (!st.isEmpty()) {
            int idx = st.pop();
            answer[idx] = (n - 1) - idx;
        }

        return answer;
    }
}

💡TIL

배운 점이 있다면 입력해주세요

  • 이 문제에서 인상 깊었던 점은 스택에 값을 넣는 것이 아니라 “인덱스”를 저장하는 방식이었다. 이 문제말고도 인덱스만 저장하는 접근방법을 종종 보았는데 이 방법을 꼭 기억해야겠다.
  • 처음에는 왜 스택/큐 문제인지 몰랐지만, 결국 이 문제는 과거 시점의 “유지 시간”을 나중에 계산하기 위한 후처리 패턴을 사용하는 문제이기에 스택을 사용한다는 것을 알게 되었다.
  • 문제를 보면 일단 브루트포스로 풀어보고, 풀린다면 이를 개선할 수 있는 구조가 무엇일지 생각해보며 접근해보자.

백준 #7576. 토마토: 그래프 / 골드5

정리한 링크: (바로가기)

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 입력 처리
    • 첫 줄에서 창고의 가로 M, 세로 N 크기를 입력받는다.
    • 그 다음 N줄에 걸쳐 토마토 상태가 담긴 2차원 리스트 box를 생성한다.
      • 1: 익은 토마토
      • 0: 익지 않은 토마토
      • 1: 토마토가 없는 칸
  2. 초기 설정
    • 큐(deque)를 생성하고, 익은 토마토(1)의 좌표를 모두 큐에 넣는다.
    • 방향 이동을 위한 dx, dy 벡터(상, 우, 하, 좌)를 설정한다.
    • 정답 변수 day = 0을 선언해, 최종 일수를 저장할 준비를 한다.
  3. BFS 수행
    • 큐가 빌 때까지 다음을 반복한다:
      • 큐에서 (x, y)를 꺼낸다.
      • 네 방향으로 이동하면서 인접한 칸이 익지 않은 토마토(0)라면:
        • 해당 칸의 값을 현재 값 + 1로 갱신한다 (며칠 째 익은 건지 누적)
        • 그 칸을 큐에 추가하여 다음 차례에 탐색할 수 있도록 한다.
  4. 결과 계산
    • 탐색이 끝난 후 2중 반복문으로 box 전체를 확인한다:
      • 0이 남아 있다면 익지 못한 토마토가 있다는 뜻이므로 1을 출력하고 종료한다.
      • 그렇지 않다면 가장 큰 값을 찾아 day에 저장한다.
  5. 정답 출력
    • 1부터 시작했기 때문에 정답은 day - 1이다. 이를 출력한다.

🚩제출한 코드

import sys
from collections import deque
input = sys.stdin.readline

# 1. 입력 처리
M, N = map(int, input().split())                            # 가로 칸 수, 세로 칸 수
box = [list(map(int, input().split())) for _ in range(N)]   # 토마토

# 2. 초기 설정
queue = deque([])                               # 큐
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)] # 방향벡터
day = 0                                         # 정답이 담길 변수

# 3. 큐에 초기 익은 토마토 위치 저장
for i in range(N):
    for j in range(M):
        if box[i][j] == 1:
            queue.append((i, j))

# 4. BFS 탐색
while queue:
    # 처음 토마토 꺼내기
    x, y = queue.popleft()

    # 처음 토마토의 인접한 토마토 찾기
    for dx, dy in directions:
        nx, ny = x + dx, y + dy

        # 범위 내에 있고, 토마토가 익지 않은 경우
        if (0 <= nx < N and 0 <= ny < M) and (box[nx][ny] == 0):
            # 익히고 1 더해주며 횟수 세기
            # 여기서 나온 제일 큰 값이 정답이 된다.
            box[nx][ny] += box[x][y] + 1  # 일수 누적
            queue.append((nx, ny))


# 5. 정답 구하기
for row in box:
    for tomato in row:
        # 모두 탐색했지만 토마토가 모두 익지 않았다면 -1 출력
        if tomato == 0:
            print(-1)
            exit()

    # 다 익혔다면 최댓값이 정답
    day = max(day, max(row))

# 6. 정답 출력
print(day - 1) # 처음에 1로 익은 토마토를 표현했으니 1을 빼준다.

💡TIL

배운 점이 있다면 입력해주세요
거리(일수) 계산은 box[nx][ny] = box[x][y] + 1 방식으로 누적해서 처리할 수 있다.


백준 #7569. 토마토: 그래프 / 골드5

정리한 링크: (바로가기)

  1. 입력 처리
    • M, N, H를 입력받고, box[H][N][M] 형태의 3차원 리스트를 만든다.
  2. 초기 설정
    • queue를 생성하고, 익은 토마토(1)의 좌표를 전부 큐에 추가한다.
    • directions: 총 6방향 설정 (위, 아래, 왼, 오, 앞, 뒤)
  3. BFS 탐색
    • 큐가 빌 때까지 다음을 반복한다:
      • 현재 좌표 (z, y, x)를 꺼낸다.
      • 여섯 방향으로 이동하며 아직 익지 않은 토마토(0)를 찾는다.
      • 해당 위치를 익게 만들고(box[nz][ny][nx] = box[z][y]+ 1) 큐에 삽입한다.
  4. 결과 처리
    • 3중 for문으로 전체 배열을 순회한다:
      • 0이 남아 있다면 1 출력
      • 아니면 최댓값을 찾아 정답은 max - 1

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

🚩제출한 코드

import sys
from collections import deque
input = sys.stdin.readline

# 1. 입력 처리
M, N, H = map(int, input().split()) # 가로, 세로, 높이
box = [[list(map(int, input().split())) for _ in range(N)] for _ in range(H)]

# 2. 초기 변수 설정
queue = deque([])
directions = [(-1, 0, 0), (0, 1, 0), (1, 0, 0), (0, -1, 0),
              (0, 0, 1), (0, 0, -1)]    # 위-오른쪽-아래-왼쪽-앞-뒤
day = 0                                 # 정답으로 반환할 변수

# 3. 초기 익은 토마토를 큐에 추가하기
for i in range(H):
    for j in range(N):
        for k in range(M):
            if box[i][j][k] == 1:
                queue.append((i, j, k))

# 4. BFS 탐색
while queue:
    z, y, x = queue.popleft()

    for dx, dy, dz in directions:
        nx, ny, nz = x + dx, y + dy, z + dz
        # 범위 내에 있고 아직 안 익은 토마토라면
        if (0 <= nx < M and 0 <= ny < N and 0 <= nz < H) and (box[nz][ny][nx] == 0):
            box[nz][ny][nx] += box[z][y][x] + 1  # 익은 날짜 누적 갱신
            queue.append((nz, ny, nx))

# 5. 정답 구하기
for height in box:
    for row in height:
        for tomato in row:
            # 안 익은 토마토가 남아있는지 여부 확인
            if tomato == 0:
                print(-1)
                exit()
        # 익는데 걸린 최대 일수 추적
        day = max(day, max(row))

# 6. 정답 출력
print(day - 1)

💡TIL

배운 점이 있다면 입력해주세요

  • 2차원 문제를 풀고 3차원 문제를 푸니 BFS 연습하는 데 도움이 되었다.
  • 다른 분의 풀이를 보고 최대 일수를 큐에 넣어 함께 관리하는 풀이로 접근해도 좋겠다는 것을 알게 되었다. 내 풀이의 경우 논리적인 흐름을 파악하기 어려운데 다른 풀이의 경우 논리적인 풀이를 한번에 파악할 수 있다는 점이 좋은 것 같다.

@Mingguriguri Mingguriguri self-assigned this May 24, 2025
@Mingguriguri Mingguriguri changed the title Minjeong / 5월 4주차 / 4문제 Minjeong / 5월 3주차 / 4문제 May 24, 2025
Copy link
Member

@YoonYn9915 YoonYn9915 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 주 그래프 탐색(BFS)문제를 다시 풀어봤는데, 두 문제 다 visited 배열에 '익은 일수'를 저장해서 정답을 출력할 때 사용한 다는 점이 인상깊었습니다. 좋은 문제 가져와주셔서 감사합니다!!

@Mingguriguri Mingguriguri merged commit 5423a29 into main May 26, 2025
@github-actions
Copy link

🔥2025-05 챌린지 진행 상황

👉 그래프

  • YoonYn9915: 3개 ❌
  • Mingguriguri: 2개 ❌

👉 구현

  • YoonYn9915: 2개 ❌
  • Mingguriguri: 2개 ❌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants