티스토리 뷰
https://school.programmers.co.kr/learn/courses/30/lessons/92344
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
위의 문제에서 완전 탐색을 수행하면 무 조 건 효율성에서 시간초과가 뜬다..
효율성을 통과할 방식을 고민해 보았으나 영 방법이 떠오르질 않아서 😅 질문 게시글을 읽었다..
처음에 내가 생각한 방식은 아래 글
다음과 같은 테스트 케이스를 예시로 들면
board =
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
skill = {
1번째 스킬 : {1, 1, 1, 2, 2, 4},
2번째 스킬 : {1, 0, 0, 1, 1, 2},
3번째 스킬 : {2, 2, 0, 2, 0, 100},
4번째 스킬 : {1, 0, 1, 1, 2, 3}
}
1 . 다음 표와 같이 각 스킬에 대한 누적 value를 구한다.
[0 ~ 0] 0 |
[0 ~ 1] -4 |
[0 ~ 2] -6 |
[0 ~ 3] 94 |
[0 ~ 4] 91 |
2. board의 각 위치에 적용되는 스킬 구간을 통하여 부분 누적 value를 계산한다.
ex )
(r, c) = (1, 1) 위치에 적용되는 스킬은 1, 2, 4 번째 스킬이므로 해당 위치의 부분 누적 value는
= [0~2] + [4~4]
= [0~2] + [0~4] - [0~3]
= -9 이다.
👉👉
이와 같은 방식의 문제점은.. "구간"을 처리하는 게 어렵다는 점이다.
각 위치에 따른 구간을 계산해야 하므로 이의 시간복잡도는 O(N*M *O(구간처리)) 이라고 할 수 있다.
근데 이 때의 구간처리 시간복잡도에 대해 O(skill)보다 효율적인 방식을 떠올리지 못하겠다는 게 문제다..
공식 풀이
https://tech.kakao.com/2022/01/14/2022-kakao-recruitment-round-1/
2022 카카오 신입 공채 1차 온라인 코딩테스트 for Tech developers 문제해설
지난 2021년 9월 11일 토요일 오후 2시부터 7시까지 5시간 동안 2022 KAKAO BLIND RECRUITMENT 1차 코딩 테스트가 진행되었습니다. 테스트에는 총 7개의 문제가 출제되었으며, 개발 언어는 C++, Java, JavaScript, K
tech.kakao.com
위의 풀이에서는 skill이 적용되는 범위에 누적되는 degree 계산을 구간 합을 이용하여 풀이하였고,
구간 합을 구하는 방식을 1차원에서 2차원으로 넓혀서 설명하고 있다.
1차원에서의 구간 합 계산 방식은 다음과 같이 두고 풀이할 수 있다.
i= 2에서부터 j=5까지의 구간에 2를 더해야 할 때.
0 | 0 | 2 | 0 | 0 | 0 | -2 |
배열의 초기값을 위와 같이 설정하고, 이 배열에 누적 합을 적용하면 원하는 구간 2 ~5 에 대해 값을 더할 수 있다.
0 | 0 | 2 | 2 | 2 | 2 | 0 |
이러한 활용을 이차원 배열에 적용해 보면 다음과 같다.
(2, 2) 부터 (3, 3) 까지의 범위에 대해 3을 더해야 할 때
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 3 | 0 | -3 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | -3 | 0 | 3 |
배열의 초기값을 위와 같이 설정하고 가로 방향(👉)에 대해 누적 합을 계산하고, 세로 방향(👇)에 대해 누적 합을 계산하면 다음과 같이 계산된다.
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 3 | 3 | 0 |
0 | 0 | 3 | 3 | 0 |
0 | 0 | 0 | 0 | 0 |
이러한 방식을 이용하여, 각 스킬마다 해당되는 위치에 초기 값을 세팅하고, 누적 합을 계산하여 해당 위치의 최종 value를 통하여 결과값을 구할 수 있다. ㅜㅜ
class Solution {
int N, M;
long[][] sum;
public int solution(int[][] board, int[][] skill) {
N = board.length;
M = board[0].length;
sum = new long[N + 1][M + 1];
init(skill);
return calBoard(board);
}
private void init(int[][] skill) {
for (int i = 0; i < skill.length; i++) {
int r1 = skill[i][1], c1 = skill[i][2];
int r2 = skill[i][3], c2 = skill[i][4];
int degree = (skill[i][0] == 1) ? -skill[i][5] : skill[i][5];
sum[r1][c1] += degree;
sum[r2 + 1][c2 + 1] += degree;
sum[r1][c2 + 1] -= degree;
sum[r2 + 1][c1] -= degree;
}
}
private int calBoard(int[][] board) {
for (int r = 0; r < N; r++) {
long total = 0;
for (int c = 0; c < M; c++) {
total += sum[r][c];
sum[r][c] = total;
}
}
int cnt = 0;
for (int c = 0; c < M; c++) {
long total = 0;
for (int r = 0; r < N; r++) {
total += sum[r][c];
sum[r][c] = total + board[r][c];
if (sum[r][c] > 0) {
cnt++;
}
}
}
return cnt;
}
}
'알고리즘 > 코테' 카테고리의 다른 글
[프로그래머스 258709] 주사위 고르기 (0) | 2025.01.11 |
---|---|
[프로그래머스 258707] n+1 카드게임 (0) | 2025.01.11 |
[프로그래머스 42891] 무지의 먹방 라이브 (0) | 2023.04.11 |
[프로그래머스 118669] 등산코스 정하기 (0) | 2023.03.29 |
[프로그래머스 92343] 양과 늑대 (0) | 2023.03.03 |
- Total
- Today
- Yesterday
- Knapsack
- 동적계획법
- prirotyqueue
- dp
- MaxHeap
- MinHeap
- 비트마스킹
- 분할정복
- Greedy
- Segment Tree
- 구간 합
- LowerBound
- 최단 거리
- 참조 지역성
- 페르마의 정리
- 배낭 문제
- 완전 탐색
- 부분 합
- Sort
- RequiredArgsConstructor
- 완전탐색
- 이분탐색
- dfs
- HashSet
- 백트래킹
- 누적 합
- 분할 정복
- 위상 정렬
- 희소 배열
- Priority Queue
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 28 | 29 | 30 | 31 |