/java-algorithm

baekjoon, programmers with java

Primary LanguageJava

Algorithm

주의 사항

테스트 케이스가 여러 개일 때 클래스 변수를 사용할 경우 루프 안에서 매번 초기화 필요

Java

배열 출력 방법

1차원 배열 - Arrays.toString(arr)
다차원 배열 - Arrays.deepToString(arr)

Long

답이 int 범위(약 20억)를 벗어나는 경우 long을 사용

Integer 배열

Integer 타입 배열의 경우 0이 아닌 null로 초기화됨

시간복잡도

1초 = 약 1억 번의 연산(n) 가능

자료구조

우선순위 큐

반복적으로 최솟값, 최댓값을 구해야 하는 경우

완전 탐색

DFS 이용

2차원 배열 탐색

재귀를 이용하여 2차원 배열을 한칸씩 탐색하는 경우 -> 몫과 나머지를 이용

// n: 행 길이, m: 열 길이
void dfs(int index) {
   if (index == n * m) {
      return;
   }
   int r = index / m;
   int c = index % m;
   // graph[r][c] = ~ 
   dfs(index + 1);
}

완전 탐색으로 시간 초과가 발생하는 경우

  1. 이분 탐색 -> 답을 mid로 두고 범위를 좁혀가며 탐색
  2. DP(메모이제이션)
  3. 투 포인터
  4. 누적합 -> 배열에 변경 지점을 표시한 후 누적해서 더함
  5. 해시

Dynamic Programming

When

  • 부분(하위) 문제로 나눌 수 있는 경우
  • 이전 선택이 다음 선택에 영향을 미치는 경우
  • 현재의 값은 최적의 값이라 생각
  • 중복 계산을 피하기 위해 값 저장
  • 구해야 하는 답을 dp로 표현

-> 점화식으로 나타내어 해결

How

  1. Bottom-up
    반복문 이용
    초기값 설정 후 값을 누적해서 채워나감
    1차원 또는 2차원 배열 이용
    인덱스를 이용해 항(구간) 표현

  2. Top-down
    재귀 이용
    종료 조건으로 초기값 반환
    파라미터를 이용해 항(구간) 표현
    Memoization을 이용하여 재귀 호출을 줄일 수 있음(가지치기)

Tip

  • IndexError 주의
  • index - 1을 하는 경우를 위해 인덱스는 1 ~ n으로 설정

조합

nCr = n-1Cr + n-1Cr-1

트리 dp

  • 특정 노드가 루트 노드인 서브 트리에서의 부분 문제로 나눔
  • 재귀 이용
  • 리프 노드에서부터 값을 계산해서 올라옴

그리디

  • 현재 상태에서의 최적 선택
  • 정렬, 우선순위 큐 이용

최단 경로

BFS

  • 가중치가 없거나 모두 동일한 경우
  • 방향까지 고려해야 하면 3차원 배열 이용

DFS는?
DFS를 사용해도 최단 경로를 구할 수 있지만 모든 경로를 탐색해야 하기 때문에 시간이 오래 걸림
BFS의 경우에는 depth를 1씩 늘려가며 탐색하기 때문에 가장 먼저 도착한 경로가 최단 경로가 됨
visited 배열로 방문하지 않은 노드만 탐색해도 BFS는 돌아가지 않지만 DFS는 돌아가는 경우가 발생

다익스트라

  • 가중치가 양수인 경우
  • 특정 노드에서 나머지 노드로의 최단 거리를 구하는 경우
  • 간선 방향을 반대로 하여 특정 노드로의 최단 거리를 구할 수도 있음

플로이드 와샬

  • 시간복잡도가 O(n^3)이므로 노드 수가 작은 경우
  • 모든 노드 간의 최단거리를 구하는 경우
  • 처음에 가중치를 초기화할 때 (Integer.MAX_VALUE/2)로 초기화 -> 가중치끼리 더해서 정수 범위 초과하는 것 방지

분리집합(Union-Find)

주의점

집합의 루트 노드를 찾고 싶을 때는 parent가 아닌 find로 찾아야 함

최소 신장 트리(MST)

  • 최소의 비용으로 모든 노드를 연결
  • 분리집합, 그리디 이용

위상정렬

  • Directed Acyclic Graph
  • 순서, 선행 관계 중 일부만 주어졌을 경우
  • 답이 여러 개 존재할 수 있음

비트마스킹

Boolean 배열을 이진수로 표현

연산

1로 만듬

bits |= (1 << n)

0으로 만듬

bits &= ~(1 << n)

같은지 검사

(bits & pattern) == bits

특정 위치가 0인지 검사

int digit = 1 << n;
(number & digit) == 0

특정 위치가 1인지 검사

int digit = 1 << n;
(number & digit) == digit

최장 증가 부분 수열(LIS)

dp 사용 시 O(n^2)에 수행 가능

최적화

이분탐색(lowerBound)을 이용하여 O(nlogn)에 수행

최소 공통 조상(LCA)

  • 트리에서 두 노드의 가장 가까운 공통 부모 노드를 찾음
  • dp를 이용하여 O(n^2) -> O(nlogn)으로 최적화 가능

최장 공통 부분 수열(LCS)

2차원 dp를 이용하여 구간 표현

KMP

  • 문자열이 특정 패턴을 포함하는지 검사
  • O(NM)(루프로 탐색 시) -> O(N+M)으로 검사 가능