일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 애드 혹
- DP
- 해시 테이블
- 맵
- 수학
- 누적 합
- 브루트포스
- 플로이드-워셜
- SSAFY
- 모던 JavaScript 튜토리얼
- 그리디
- 트리
- 그래프
- 투 포인터
- 정수론
- 구현
- 슬라이딩 윈도우
- boj
- 이분 탐색
- 13164
- 에라토스테네스의 체
- 문자열
- JavaScript
- 싸피
- DFS
- 세그먼트 트리
- Python
- 2357
- BFS
- 정렬
- Today
- Total
목록알고리즘 (251)
흙금이네 블로그
아이디어 플로이드-워셜 알고리즘으로 모든 건물 간 거리를 구한 후, 왕복 시간을 최소로 하는 두 건물의 조합을 찾는다. 풀이 #1 (Python) 건물 개수 N은 100 이하이므로 모든 건물 간 거리를 저장하는 2차원 리스트 D를 생성하여 100으로 채운다. 같은 건물 간 거리는 0으로 저장하고, 입력 받은 도로 정보를 D에 반영한다. 플로이드-워셜로 건물 i에서 j로 가는 시간을 건물 k를 경유하여 가는 시간과 비교해 최솟값으로 갱신해 나간다. 양방향 도로이므로 건물 j에서 건물 i에서 가는 시간도 같은 값으로 저장하며, j는 i보다 큰 번호부터 시작하도록 한다. 모든 건물 간 거리를 구한 후, 이중 for문에서 건물 i와 j를 선택했을 때의 왕복 시간 합을 구해 결과값을 갱신한다. import sys..
아이디어 #1 동적 계획법으로 사용하는 동전의 최소 개수를 구한다. 풀이 #1 k+1로 초기화된 k+1 길이의 리스트를 dp를 생성한다. 차례로 입력 받은 동전의 가치 c가 k보다 크거나 중복되는 동전인 경우 continue로 건너뛰고, 아니면 dp[c]에 1을 저장한다. c보다 큰 가치 합들에서 각각 c를 뺀 가치 합의 사용 동전 최소 개수보다 1 큰 값과 비교해 dp의 최솟값을 갱신한다. 가치 합을 k로 만들 수 있으면 사용하는 동전의 최소 개수를 출력하고, 그렇지 않으면 -1을 출력한다. import sys input = sys.stdin.readline def solution(): n, k = map(int, input().split()) dp = [k+1]*(k+1) for _ in range(..
아이디어 동적 계획법으로 경우의 수를 더해 나간다. 풀이 가치 합을 인덱스로 하여 경우의 수를 저장하는 리스트 dp를 생성한다. k보다 큰 값은 고려할 필요가 없으므로 dp의 길이는 k+1로 하고, 인덱스 0의 값은 1, 나머지는 0으로 채운다. 인덱스 0의 값을 1로 채우는 이유는 이후 for문에서 동전 가치의 경우의 수를 증가시키기 위함이다. 차례로 입력 받은 동전의 가치 c로 c보다 더 작은 가치는 만들 수 없으므로 for문에서 가치 합을 c부터 시작한다. c 이상의 가치 합 j의 경우의 수 dp[j]에 j에서 c를 뺀 가치의 경우의 수 dp[j-c]를 더해 나간다. import sys input = sys.stdin.readline def solution(): n, k = map(int, inpu..
아이디어 표에서 조건에 맞게 칸을 이동하며 만들 수 있는 숫자들 중 가장 큰 완전 제곱수를 구한다. 풀이 #1 (Python) 표를 입력 받아 2차원 리스트 table에 저장하고, 만들 수 있는 숫자들을 저장하는 세트 numbers를 생성한다. 차례로 표의 i행 j열에 있는 숫자를 numbers에 추가하고, 행과 열의 공차 di, dj로 함수 make_number를 호출한다. 이때 행과 열의 공차가 모두 0이면 무한 루프에 빠지므로 둘 중 하나라도 0이 아닐 때 함수를 호출하도록 한다. 함수 make_numbers는 인덱스를 벗어나지 않는 범위에서 재귀 호출로 공차에 따라 칸을 이동하며 숫자를 이어 붙인다. 이어 붙인 숫자들을 numbers에 추가하며, 공차가 음수인 숫자들을 저장하기 위해 역순으로 이어..
아이디어 문자열의 접두사와 접미사가 일치하면서 문자열 중간에 등장하는 가장 긴 부분 문자열을 찾는다. 풀이 숫자 0~9는 성냥개비 2~7개로 모두 표현할 수 있다. 리스트 M에 인덱스만큼의 성냥개비로 만들 수 있는 가장 작은 수를 저장한다. 리스트 dp에 인덱스 7까지는 M과 같은 값들을 저장하고, 인덱스 8에는 10을 저장하여 for문이 9부터 시작하도록 한다. 인덱스 8을 이후 for문에서 접근하면 dp[8-7]로 dp[1]을 가리켜 값이 잘못 저장되기 때문이다. 성냥개비 2~7개마다 자릿수가 하나씩 늘어나므로 이전 수에서 자릿수를 늘려 만들 수 있는 가장 작은 수를 저장해 나간다. 성냥개비로 가장 큰 수를 만들기 위해서는 가능한 적은 성냥개비를 사용하여 자릿수를 크게 만드는 것이므로, 성냥개비 2개..
아이디어 #1 라그랑주에 의해 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명되었으므로 7453번 - 합이 0인 네 정수처럼 두 제곱수를 더한 값들에서 투 포인터로 합이 n이 되는 네 제곱수를 찾는다. 풀이 #1 (Python) 딕셔너리 cnt_dict에 두 제곱수 합을 키로, 0이 아닌 제곱수의 개수를 값으로 저장한다. 입력 n이 50,000 이하로 주어지므로 제곱수의 제곱근은 223 이하로 설정하고, 0은 제곱수가 아닌 것으로 본다. 세트 numbers에 두 제곱수 합들을 저장한 후 numbers를 오름차순으로 정렬한 리스트로 대체한다. 투 포인터를 이용해 numbers에서 네 제곱수 합이 n인 경우를 찾아 최소 제곱수 개수를 갱신해 나간다. n = int(input()) c..
아이디어 문자열의 접두사와 접미사가 일치하면서 문자열 중간에 등장하는 가장 긴 부분 문자열을 찾는다. 풀이 문자열 S에 대한 부분 일치 테이블 lps를 만든다. S의 접두사와 접미사가 일치하면서 가장 긴 부분 문자열 S[-j:]가 문자열 S의 중간에 등장하면 S[-j:]를 출력한다. S의 중간에 등장하지 않으면 그 다음 길이의 부분 일치 문자열을 찾아 출력하고, 없으면 -1을 출력한다. lps[-1]이 0이면 슬라이싱이 S[-0:]로 되어 문자열 S를 나타내고, S는 S[1:-1]에 포함되지 않아 if문이 실행되지 않는다. 또 lps[-1]-1은 -1이 되어 lps[-1]을 가리키게 되므로 elif문도 실행하지 않고 else문의 -1을 출력한다. def solution(): S = input() N = ..
아이디어 가능한 세 자릿수에서 각 질문에 대한 대답에 따라 불가능한 경우를 제외해 나간다. 풀이 #1 (Python) 세트 numbers에 1~9의 숫자 중 서로 다른 숫자 세 개로 구성된 세 자릿수를 문자열로 저장한다. 질문마다 질문한 숫자는 문자열로 Q에, 스트라이크 개수와 볼 개수는 정수로 strike와 ball에 저장한다. numbers에 있는 수를 구성하는 각 숫자가 Q와 자릿값까지 같으면 s를, 그렇지 않고 Q에 포함되면 b를 증가시킨다. 해당 숫자의 s와 b가 각각 strike와 ball에 같다면 temp에 추가하고, for문 종료 후에 기존의 numbers를 temp로 대체한다. import sys input = sys.stdin.readline def solution(): numbers ..
아이디어 DFS로 말단 직원에서부터 자신의 부하들에게 전화하는 데 걸리는 가장 긴 시간을 DP로 구해 나간다. 풀이 상사 번호를 리스트 P에 저장하고, 부하 직원의 번호를 상사 번호에 맞게 2차원 리스트 child에 저장한다. 함수 dfs에서는 자식 노드들을 탐색하여 구한 자식 노드에서 가장 오래 걸리는 시간을 빈 리스트 temp에 추가한다. 내림차순 정렬한 temp의 각 요소들과 그 순번을 더한 값 중 최댓값을 해당 노드에서 가장 오래 걸리는 시간으로 저장한다. 리프 노드에서는 자식 노드가 없어 temp가 빈 리스트이므로 for문과 if문 진입 없이 함수가 종료된다. 0번 직원부터 함수 dfs를 호출한 후 0번 직원의 dp 테이블에 저장된 결과값을 출력한다. def dfs(idx): temp = [] ..
아이디어 규칙을 찾아 간단하게 계산할 수 있는 부분은 계산하여 처리하고, 나머지는 브루트포스로 처리한다. 풀이 #1 (Python) 한 자릿수 앞에는 0이 붙으며, 00부터 59까지의 수에서 0~5는 15번씩, 6~9는 6번씩 등장한다. K가 등장하는 횟수를 m이라 한다면 00분 00초부터 59분 59초까지 K가 등장하는 총 횟수 x는 초와 상관없이 분에서 K가 등장하는 횟수와 분과 상관없이 초에서 K가 등장하는 횟수의 합(m×60×2)에서 분과 초에서 동시에 K가 등장하는 횟수(m^2)를 빼서 K가 0~5일 때는 1575, K가 6~9일 때는 684가 된다. 시에 대해서는 계산식을 세우는 것이 더 복잡할 것 같아 for문에서 문자열로 K의 포함 여부를 확인하도록 한다. 만약 시에서 K가 등장하면 분과 ..