[Java]백준 17470 배열 돌리기 5

출처 https://www.acmicpc.net/problem/17470 접근 시간복잡도 분석 문제에서 주어진 배열의 크기는 최대 100 x 100이고, 전체 연산의 개수는 2,000,000개 이므로, 일반적인 회전을 구현할 경우 시간 초과가 발생합니다. O(N) = 100 x 100 x 2,000,000 = 2 x 10^13입니다. 배열 연산 압축하기(X) 해당 접근은 잘못된 풀이입니다. 올바른 풀이는 아래를 참고하시기 바랍니다. 연산을 구현하고 배열을 돌리다 보면, 뭔가 최적화할 수 있는 것 같은 느낌이 듭니다. 상하(1)-좌우(2) 반전 2번 하면 원래 배열로 복귀합니다. 오른쪽(3) 왼쪽(4) 회전 ...

2024. 12. 31. · 6 분 · 1273 단어 · Leaf

[Java]Programmers 멀쩡한 사각형

출처 프로그래머스 멀쩡한 사각형 접근 규칙을 알고 나면 구하기 쉽지만, 모르면 생각보다 까다로운 문제입니다. 규칙 구하기 주어진 예시 (w = 8, h = 12)에 대해 규칙을 확인해보겠습니다. 문제의 예시를 자세히 보면 작은 사각형이 반복되는 것을 알 수 있습니다. w = 8과 h = 12의 최대공약수인 4개의 사각형이 생성됩니다. 즉, 최대공약수로 해당 길이를 나누었을 때 생성된 작은 사각형의 잘린 개수를 구하면 됩니다. 최대공약수로 나눠진 사각형(nw x nh = 2 x 3)의 잘린 개수는 다음과 같이 구할 수 있습니다. ...

2024. 12. 23. · 3 분 · 442 단어 · Leaf

[Java]코드트리 메두사와 전사들 문제 해설

출처 메두사와 전사들 접근 복잡한 문제인만큼 구현하면서 순차적으로 처리해야 할 과정이 많은데, 이에 필요한 알고리즘을 정리해보면 다음과 같습니다. 메두사의 이동경로 구현 BFS + 경로 역추적 시선 생성 배열 탐색 구현 병사 이동 및 공격 배열 탐색 구현 알고리즘 자체는 어렵지 않으나, 배열 탐색을 구현하는 과정이 복잡합니다. 메두사 이동경로 구현(BFS) 메두사가 이동하는 과정에 장애물이 있기 때문에, BFS를 통해 미로를 탐색하는 최단경로를 구해야 합니다. 또한, 이동경로를 다시 돌면서 병사들과의 상호작용을 확인하기 위해 이러한 경로를 별도 배열에 저장해야 합니다. ...

2024. 12. 21. · 15 분 · 3020 단어 · Leaf

[Java]Programmers 수식 최대화(2020 KAKAO Internship)

출처 수식 최대화(2020 KAKAO Internship) 접근 완전탐색(DFS) 각 연산자의 우선순위를 변경하면서 전체 탐색을 하고, 변경된 우선순위마다 수식을 계산해서 최댓값을 갱신합니다. 연산자 순서에 따라 결과가 달라지므로, 순열(Permutation)에 해당합니다. 다양한 구현방법이 있지만, 개인적으로 다양한 조건을 만족하는 순열(조합)을 빠르게 구현할 수 있는 DFS를 선호합니다. 3가지 연산자만 있으므로, 모든 경우의 수를 구해도 6가지이기 때문에 시간복잡도는 충분합니다. 후위 표기 변환(InFix to PostFix) 보통 사람이 계산을 할 때는 A + B * C의 형태로 수식을 써서 계산을 합니다. 이 때, A와 B 사이에 연산자가 있는 형태를 중위 표기(InFix)라고 합니다. ...

2024. 12. 18. · 4 분 · 817 단어 · Leaf

[Java]백준 1005 ACM Craft

출처 백준 1005 ACM Craft 접근 완전탐색(BFS) 특정 건물이 나올때까지 각 건물들을 탐색하는 과정을 BFS로 구현할 수 있습니다. 건물 사이의 관계(간선)의 개수가 100,000이므로, 각 간선을 한번씩만 방문한다면 시간복잡도 내 풀이가 가능합니다. 위상 정렬 각 건물은 해당 건물이 지어지기 전에 특정 건물을 지어야 하는 선행조건이 있습니다. 이를 구현하기 위해 위상정렬을 활용할 수 있습니다. 위상정렬은 다음과 같이 해당 건물을 짓기 전에 선행되어야 하는 건물이 모두 지어졌는지(선행 건물의 개수가 0인지) 확인하는 과정을 통해 구현할 수 있습니다. ...

2024. 12. 15. · 3 분 · 465 단어 · Leaf

[Java]백준 9202 Boggle

출처 백준 9202 Boggle 접근 Backtracking 특정 단어를 한 글자씩 찾아들어가면서 단어 사전에 존재하는지 확인하는 방식은 전형적인 DFS의 형태입니다. 주어진 단어의 개수가 w < 300,000 이지만 탐색해야 하는 전체 Boggle 보드의 크기가 4X4이고, 이러한 Boggle의 개수가 b < 30이기 때문에 DFS 자체는 많은 시간복잡도가 필요하지 않습니다. DFS 탐색 과정에서 다음 글자를 추가했을 때, 단어 사전에 포함된 단어를 만들 수 있는지를 빠르게 확인하여 불가능한 경우를 가지치기(pruning)한다면, 시간복잡도를 더욱 줄일 수 있습니다. 이러한 기법을 Backtracking이라고 합니다. ...

2024. 12. 10. · 4 분 · 821 단어 · Leaf

[Java]Programmers 순위 검색(2021 KAKAO BLIND RECRUITMENT)

출처 2021 KAKAO BLIND RECRUITMENT 순위 검색 접근 와일드카드 검색 와일드카드(-) 없이 검색을 구현하는 것은 각 지원자의 속성에 코딩테스트 점수를 저장하면, 속성별로 검색이 가능하기 때문에 큰 어려움이 없습니다. 와일드카드가 없는 상황은 다음과 같이 트리 구조로 데이터를 저장할 수 있습니다. 트리 구조로 지원자 정보를 저장합니다. 리프 노드에는 리스트로 코딩테스트 점수를 저장합니다. 하지만, 문제에서 주어진 것처럼 쿼리 시 와일드카드가 나오면 모든 정보를 포함하도록 탐색을 해야 하기 때문에 이를 구현하기 위해 별도의 공간에 와일드카드 속성들을 저장해야 합니다. ...

2024. 12. 4. · 3 분 · 529 단어 · Leaf

[Java]백준 14942 개미

출처 백준 개미 접근 완전탐색(DFS) 자식 방에서 부모(Root) 방향으로 DFS를 하면서 지상에 도달하는데 걸리는 시간을 확인합니다. 개미 방의 개수가 최대 10^5이므로, 최악의 경우인 방이 일렬로 나열된 경우를 고려해야 합니다.1 선형적인 DFS로는 시간복잡도가 초과할 것이라고 생각해서 BinarySearch로 최적화를 했는데, 선형으로 조상들을 탐색해도 시간초과가 되지 않는 것으로 보아 DFS 만으로도 풀 수 있을 것 같습니다. TREE + BinarySearch 문제를 다시 읽어보면 자신 부모들의 집합, 즉, 조상들을 하나씩 타고 올라가면서 갈 수 있는 최대 조상의 번호를 반환해야 함을 알 수 있습니다. ...

2024. 12. 3. · 4 분 · 762 단어 · Leaf

[Java]Programmers 숫자 타자 대회

출처 프로그래머스 숫자 타자 대회 접근 완전탐색 이전 숫자에서 왼손과 오른손을 움직여서 다음 숫자를 누르는 모든 경우를 방문하게 되면 매번 2번씩 방문이 발생합니다. 1,000개의 숫자를 왼손과 오른손으로 모두 누르려면 2^1000의 시간복잡도가 필요합니다.1 이는 불가능하므로, 완전탐색만으로는 풀이할 수 없습니다. DP 문제에서 필요한 값은 최솟값이니, 완전탐색 중 최솟값들만을 저장하면서 계산하면 100*1000 = 10^6으로 시간복잡도를 줄일 수 있습니다. 이전 값들 중 최솟값만 저장하면서 완전탐색을 최적화합니다. 위 과정을 자세히 살펴보면, 처음 위치[l : 4], [r : 6]에서 0번 패드를 누르려면 2가지 경우가 발생합니다. 이 경우에는 중복되는 가짓수가 없으니 진행합니다. 다음 위치[l : 0, 4], [r : 6, 0]에서 1번 패드를 누르려면 각각 2가지씩 총 4가지 경우가 발생합니다. 이 경우에도 중복되는 가짓수가 없으니 진행합니다. 다음 위치[l : 1, 1, 0, 4], [r : 6, 0, 1, 1]에서 3번 패드를 누르려면 각각 4가지씩 총 8가지 경우가 발생합니다. 이 경우 더 작은 값만을 저장하여 가지치기가 가능합니다. 좀 더 자세히 살펴보기 위해, 다른 경우는 제외하고 첫번째 중복의 경우만 추적해보겠습니다. 두 경우의 총 가중치를 비교해서 작은 값만을 남깁니다. ...

2024. 11. 28. · 4 분 · 831 단어 · Leaf

[Java]Programmers 혼자 놀기의 달인

출처 프로그래머스 혼자 놀기의 달인 접근 숫자 더미를 여러 그룹으로 분리한 뒤, 가장 큰 그룹과 두번째로 큰 그룹을 선택합니다. 완전탐색(DFS) DFS를 통해 숫자 더미를 여러 그룹으로 분리할 수 있습니다. 문제에서 주어진 카드의 최대 개수가 100 이하이므로, 한번씩 방문한다면 O(N)으로 해결이 가능합니다. 100개의 카드가 1개의 그룹인 경우, DFS의 최대 Depth가 100이므로 재귀 호출을 하더라도 StackOverFlow1가 발생하지 않습니다. 재귀 호출을 통해 그룹 분리하기 풀이 import java.util.*; class Solution { // 카드 그룹을 넣을 전역변수 List<Integer> group; public int solution(int[] cards) { group = new ArrayList<>(); // 방문 체크를 위한 변수 boolean[] visited = new boolean[cards.length + 1]; // 카드를 돌면서 그룹화 for (int card : cards) { // 이미 방문한 카드는 다시 방문하지 않음 if (visited[card]) continue; // DFS dfs(card, 0, cards, visited); } // 그룹이 1개면 0 반환 if (group.size() == 1) return 0; // 내림차순 정렬 후 가장 큰 그룹과 두번째로 큰 그룹 곱해서 반환 group.sort(Comparator.reverseOrder()); return group.get(0) * group.get(1); } // DFS void dfs(int now, int cnt, int[] cards, boolean[] visited) { // 이미 방문한 그룹이 다시 등장 -> 같은 사이클(그룹)이므로 그룹에 현재 개수 추가 if (visited[now]) { group.add(cnt); return; } // 방문 체크 visited[now] = true; // now에서 1을 빼줘야 배열 범위를 벗어나지 않음, 방문할 때마다 현재 그룹의 개수 1개씩 추가 dfs(cards[now - 1], cnt + 1, cards, visited); } } 결과 소요시간 7:41 ...

2024. 11. 25. · 2 분 · 315 단어 · Leaf