본문 바로가기

CS/APS

(19)
[엘리스 알고리즘 코드 챌린지] Day 5. 수열 복원 (Java) 문제핵심핵심 로직단순한 방법으로는 모든 부분 수열의 합 조합을 제거하는 것이다.수열이 [1, 2, 4] 인 경우를 생각하면모든 부분 수열의 합은 아래와 같다.0a1a2a3a1 + a2a1 + a3a2 + a3a1 + a2 + a3 a1, a2, a3는 원래의 수열이고 그 외의 것들은 a1, a2, a3를 조합하여 합한 것임을 알 수 있다.따라서 주어진 부분 수열의 합을 정렬하고 작은 수부터 짝지어 합한 후 제외하면 결과적으로 원래의 수열이 남게 된다. 예를 들어 [0 1 2 3 4 5 6 7] 이 주어졌다면, 일단 공집합 0을 제외하고1 + 2 = 3 제거 [1 2 3 4 5 6 7]1 + 4 = 5 제거 [1 2 3 4 5 6 7]1 + 6 = 7 제거 [1 2 3 4 5 6 7]2 + 4 = 6 제거..
[엘리스 알고리즘 코드 챌린지] Day 4. 트리 위의 게임 (Java) 문제핵심두 플레이어는 항상 최선의 선택을 한다고 하였다.내부 노드는 후공이 최대한 낮은 점수를 받도록 다음 노드를 선택해야한다.리프 노드에서는 선공이 항상 승리한다. (공격하고 바로 끝나기 때문에)내부 노드에서 시작하는 경우는 최종 결과가 자식 노드의 결과와 연관되어 있다.그리고 리프 노드에서 시작하는 경우는 확정적이기 때문에 리프 노드에서 시작하는 경우를 기반으로 루트에서 시작하는 경우까지 점차 확장해가면 해결할 수 있다.구현1번 예제의 트리 모양은 아래와 같다.  1 /|\2 3 5 /4 이를 기반으로 구현을 한다면 DP 테이블 정의D[i] : i번 노드에서 시작했을 때, 선공과 후공의 점수차 (둘 다 최선의 선택을 한 경우) 초기값 (리프 노드에서 시작하면 선공으로 점수를 얻고 바로 종료된다)D[..
[Baekjoon Online Judge] 19951. 태상이의 훈련소 생활 (Java) 핵심N과 M이 최대 100,000이다.완전 탐색 시, 최악의 경우 시간복잡도가 O(NM)이므로 시간초과이다. 이와 같이 큰 범위를 다룰 때, 시간을 줄이기 위한 방법의 하나로 누적합이 있다.누적합이름에서 유추할 수 있듯이 값을 계속해서 쌓는 것이다.e.g. [1, 2, 3, 4, 5] 의 누적합을 원소로 하는 배열은 [1, 3, 6, 10, 15] 기존 배열의 인덱스 2~4 범위의 합을 구하려면, 가장 단순한 방법은 해당 범위를 순회하며 일일이 합하는 것이다. 누적합 배열 acc를 이용하면 acc[4] - acc[1]로 O(1)에 계산할 수 있다. 이 문제의 경우는 누적합 아이디어를 사용하면 해결할 수 있다. 우선 상태를 기록할 새로운 배열 acc를 만든다.조교 1이 2~4번 칸에 흙을 3만큼 쌓으라고 ..
[Baekjoon Online Judge] 1822. 차집합 (Java) 핵심두 배열의 길이가 500,000이다.따라서 배열 A의 각 원소가 배열 B의 원소에 포함되어 있는지 일일이 확인한다면 시간복잡도는 O(N^2)이 된다. (시간 초과) 따라서 시간복잡도를 줄여야 한다.원소가 많은 배열에서 특정한 원소가 포함되어 있는지 확인해야하는 문제이다.이분 탐색에 대해 알고 있다면 대부분 쉽게 떠올릴 수 있을 것이다. (모르겠다면 이분 탐색, 3분 안에 이해하기 참고) 그럼 시간복잡도는 O(NlogN)으로 줄고 여유있게 풀 수 있다.Code (Java)import java.io.IOException;import java.util.*;import static java.util.Collections.binarySearch;public class Main { public static..
[Baekjoon Online Judge] 14719. 빗물 (Java) https://www.acmicpc.net/problem/14719 핵심특정 지점을 기준으로 두 값을 찾는다.1. 해당 지점의 블록 높이2. 해당 지점을 기준으로 왼쪽의 땅에서 가장 높은 블록과 오른쪽 땅에서 가장 높은 블록 중에서 더 낮은 블록을 찾는다. 2번 값이 해당 지점에서 빗물이 최대로 쌓일 수 있는 높이이다.따라서 2번과 1번의 차가 해당 지점에서 쌓일 수 있는 빗물의 최대 높이(만약 이 차가 0 이하라면 빗물이 한 칸도 쌓일 수 없는 상태)+ 양 끝은 빗물이 쌓일 수 없다.구현나는 왼쪽을 기준으로 현재 인덱스까지 지점에서 가장 높은 블록의 높이를 배열에 저장했다. (누적합)e.g. highestFromLeft[10] : 0 ~ 10 지점 중에서 가장 높은 블록의 높이 오른쪽도 똑같이 구한 후..
[Baekjoon Online Judge] 1620. 나는야 포켓몬 마스터 이다솜 https://www.acmicpc.net/problem/1620 핵심N, M은 최대 100,000이다. 배열의 인덱스는 숫자이기 때문에포켓몬 번호가 주어졌을 때 포켓몬 이름을 찾는 것은 배열로 가능하지만포켓몬 이름이 주어졌을 때 포켓몬 번호를 찾는 것은 배열로 불가능하다.그렇다고 일일이 배열을 탐색하면 O(N)의 탐색을 N번 수행하므로 O(N^2)의 시간복잡도가 된다. (시간 초과) 따라서 String으로 O(1)에 탐색이 가능하면서 Key, Value 형태로 데이터를 저장하여 대응하는 포켓몬 번호까지 쉽게 가져올 수 있는 해시 맵을 사용할 것이다. Code (Java)import java.io.BufferedReader;import java.io.InputStreamReader;import java...
[Baekjoon Online Judge] 7785. 회사에 있는 사람 (C++, Java) https://www.acmicpc.net/problem/7785 핵심N은 최대 1,000,000이다.leave 로그마다 모든 enter 로그를 일일이 찾는 방법을 사용했을 때,만약 N/2개의 enter 로그가 연달아 나오고 그 다음 N/2개의 leave 로그가 연달아 나온다면N/2개의 enter 로그를 N/2개의 leave 로그에 대해 탐색해야 하므로 O(N^2)의 시간복잡도를 갖는다. (시간초과) 따라서 탐색 시간을 줄여야 한다. 여러 방법이 있는데 나는 해시 자료구조를 사용하는 방법을 사용했다.해시 자료구조의 탐색은 O(1)의 시간복잡도를 갖는다.이를 활용하면 앞선 상황에서 O(N)의 시간복잡도를 갖는다.Code (C++) with std::unordered_set#include #include u..
[Baekjoon Online Judge] 1806. 부분합 (C++, Java) 핵심가장 단순한 방법인 3중 반복문을 이용하는 방법은 O(N^3) (시간초과) 누적합과 투 포인터 알고리즘에 대해 알고 있다면 쉽게 떠올릴 수 있다.이 두 개념을 활용하면 시간복잡도가 O(N)으로 줄어든다. 두 포인터가 부분 수열의 양 끝을 가리키고 (부분 수열의 합이 S보다 커야한다는) 조건에 맞게 포인터를 조절한다. 앞 인덱스가 뒷 인덱스를 역전할 때까지 반복부분 수열의 합이 S보다 작다면, 크거나 같아질 때까지 뒷 인덱스를 1 증가시키고 해당 인덱스에 해당하는 원소를 추가한다.조건에 부합하는 최소 부분 수열의 길이를 갱신한다.부분 수열의 합이 S보다 크거나 같다면, 앞 인덱스에 해당하는 원소를 빼고 1 증가시킨다.Code (C++)#include using namespace std;#define M..

728x90
반응형