Lai_Khan
개발 & 공부 일지
Lai_Khan
전체 방문자
오늘
어제
  • 전체보기 (69)
    • 공부 (60)
      • 자료구조 & 알고리즘 (4)
      • 웹 (1)
      • JAVA (3)
      • Spring (8)
      • JPA (0)
      • 네트워크 (4)
      • Kubernetes (4)
      • Typescript (5)
      • React (1)
      • 기타 (3)
      • [부스트코스] 웹 프로그래밍 (13)
      • 정보처리기사 (1)
      • 백준 2020년 1~2월 알고리즘 (12)
    • 프로젝트 (0)
    • 취준 (1)
    • 책 (3)
    • 잡담 (5)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • 벡엔드
  • http
  • 백엔드
  • java
  • API
  • proxy
  • 코드리뷰
  • 자바
  • JPA
  • 객체
  • OutOfPath
  • typescript
  • 스프링
  • 네트워크
  • kubernetes
  • 브라우저
  • 부스트코스
  • 웹
  • Spring
  • 클래스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Lai_Khan

개발 & 공부 일지

4번째 수업
공부/백준 2020년 1~2월 알고리즘

4번째 수업

2020. 1. 19. 22:43
이 글들은 백준 온라인 저지의 백준님이 2020년 1~2월에 강의하시는 강의 내용을 듣고 복습한 뒤 간단하게 정리하여 올리는 글이다. 이 글을 쓰는 이유는 그날그날 들은 강의 내용을 복습하고 정리함으로써 배운 것을 확실히 머리에 남김과 동시에 나중에 다시 상기시킬 때 도움이 되도록 하기 위함이다.

● 브루트포스 - 백트래킹

백트래킹은 브루트포스의 유형 중 하나다. 브루트포스가 모든 방법을 다 시도하는 것이라면 백트래킹은답의 가능성이 없으면 더이상 호출하지 않고 잘라버리는 것(커팅)이다.

 

△ 문제 - 부등호

문제 : 부등호 기호 <와 >가 나열된 수열 A가 있다. 기호의 앞 뒤에 한자리 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 이때, 선택된 수는 모두 달라야한다. k개의 부등호 관계를 모두 만족시키는 (k+1)개 자리의 정수 중 최대값과 최소값을 구하는 문제

 

방법1

1. 수를 채운다.

2. 부등호 관계를 만족하는 지 검사

방법의 수 : (k+1)!개

시간 복잡도 O((k+1)!*k)

 

방법2

위의 방법은 부등호 기호를 만족하는지 마지막에 검사를 한다. 함수의 호출 중간에 정대로 정답이 될 수 없는 경우를 발견하면 그 뒤의 호출은 더 이상 진행하지 않아도 된다.

 

△ 문제 - 맞춰봐

문제 : -10부터 10까지 N(1≤N≤10)개의 정수로 이루어진 수열 A가 있다. S[i][j] = A[i]+A[i+1]+...+A[j]가 0보다 크면 +, 작으면 -, 같으면 0. S가 주어졌을때 가능한 A를 아무거나 찾는 문제.

 

방법1

21개의 수를 10개의 자리에 넣어야한다.

총 경우의 수 : 21^10 = 16,679,880,978,201

시간초과

 

방법2

-10부터 10까지 다 돌아보지 말고 부호에 따라 '+'면 1~10, '-'면 -10~-1, '0'인 경우에는 0능 넣는 방식으로 계산

시간초과

 

방법3

모든 기호를 먼저 검사하고 돌아보기

S[k][index] (0≤k≤index)를 재귀함수 go(index)에서 검사

함수의 호출 중간에 정대로 정답이 될 수 없는 경우를 차단

 

● 브루트포스 - 순열

모든 순서를 다 살펴봐야 할때 사용한다. 그러나 느리다

1. 첫 순열 만들고

2. 다음 수열을 만드는 함수 구하기

C++이면 STL의 함수 next_permutation, prev_permutation를 사용하면 간단하다.

 

다음 순열

사전적으로 다음에 오는 순열을 찾는 방법

1. A[i-1] < A[i]를 만족하는 가장 큰 i를 찾는다.

2. j≥i이면서 A[j]>A[i-1]을 만족하는 가장 큰 j를 찾는다.

3. A[i-1]과 A[j]를 swap한다.

4. A[i]부터 순열을 뒤집는다.

시간복잡도 O(N)

 

△ 문제 - 외판원 순회 2

영어로 Travelling Salesman Problem(TSP)이라고 한다.

문제 : 1번부터 N번까지 번호가 매겨져 있는 도시가 있다. 한 도시에서 시작해 N개의 모든 도시를 거쳐 다시 원래 도시로 돌아오려고 한다. 한 번 갔던 도시는 다시 갈 수 없다. 이때, 가장 적은 비용을 구하는 문제.

 

방법

2≤N≤10이므로 시간복잡도는 O(N*N!)이다. 모든 경우를 다해봐도 된다.

첫 순열부터 마지막 순열까지 모든 비용을 계산해 최소값을 출력한다.

 

● 브루트포스 - 비트마스크

비트마스크 : 변수 하나로 많은 데이터를 저장 가능

정수로 집합에 관한 정보를 넣는다. 보통 0부터 N-1까지 정수로 이루어진 집합을 나타낼때 사용한다.

예) {1, 3, 4, 5, 9} = 570 = 2^1+2^3+2^4+2^5+2^9

전체집합 : (1 << N) -1

공집합 : 0

기본 연산 : 추가, 검사, 제거 

추가 : S | (1 << i)

검사 : S & (1 << i)

제거 : S & ~(1 << i)

토글 : S ^ (1 << i)

비트연산을 사용할 때는 연산자 우선순위를 생각해야 한다.

 

△ 문제 - 부분수열의 합

문제 : 서로 다른 N개의 정수의 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 문제

모든 부분수열의 개수 = 2^N (1≤N≤20)

 

방법

전체집합=(1<<N)-1

크기가 0인 부분수열은 제외

집합에 무엇이 포함되어있는지 확인

 

△ 문제 - 수들의 합 2

문제 : N개의 수로 된 수열 A[1], A[2], ..., A[N]이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i]+A[i+1]+...+A[j]가 M이 되는 경우의 수를 구하는 문제

총 3가지 시간복잡도로 해결할 수 있다.

 

방법1

A[i]+A[i+1]+...+A[j] == M이 되는 (i, j)쌍을 찾는 문제와 같다.

i를 정하고, j를 정하고, 합을 계산하면 O(N^3)로 계산할 수 있다.

 

방법2

i=a, j=b인 경우의 합과 i=a+1, j=b인 경우의 차이는 A[b+1]밖에 없다.

합을 계산할 때, 합을 각각의 i에 대해서 누적하면 O(N^2)로 계산할 수 있다.

 

방법3

각각 i=a, j=b인 경우와 i=a+1, j=b인 경우에 대해 생각해 봤을때,

A[a]+A[a+1]+...+A[b] < M

A[a]+A[a+1]+...+A[b]+A[b+1] > M

이 경우, j를 계속 증가시키는 것은 의미가 없기 때문에 i를 증가시켜야 한다.

즉, sum이 sum<M에서 sum>M이 되는 순간에 i를 증가시킨다.

시간복잡도 = O(N)

 

● 중간에서 만나기

Meet in the Middle

문제를 절반으로 나눠서 양쪽 절반에서 모든 경우를 다 해보는 방법

 

△ 문제 - 부분수열의 합 2

문제 : 서로 다른 N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 문제

 

방법

주어진 수열을 반으로 나눈다. 각각 Up, Down.

각각의 수열에 대하여 모든 경우를 나열한다.

L과 R을 이동시키며 합이 S가 되는 경우를 센다.

 

△ 문제 - 합이 0인 네 정수

문제 : 크기가 N인 배열 A, B, C, D가 있다. 이때, A[a], B[b], C[c], D[d]의 합이 0인 (a, b, c, d) 쌍의 개수를 구하는 문제

 

방법

총 가능한 경우의 수 : N^4가지

절반으로 나눠서 A[a]+B[b] = N^2가지,  C[c]+D[d] = N^2가지 로 계산해 볼 수 있다.

 

● 그래프

다이나믹은 점화식이 문제마다 다르고, 브루트포스는 만드는 방법이 달랐다.
하지만 그래프는 알고리즘이 딱 있다. 변하지 않는다. (DFS, BFS)
문제의 상황을 어떻게 그래프로 만들거냐가 더 중요하다.

 

§ 특징

정점(Node)과 간선(Edge)으로 이루어짐. G = (V, E)

경로 : 정점A에서 B로 가는 경로 (A->B->C)

사이클 : 정점 A에서 다시 A로 돌아오는 경로 (A->B->C->A)

단순경로와 단순사이클 : 경로/사이클에서 같은 정점 방문하지 않는다.

가중치★★★ : 지나갈때마다 소비해야하는 비용
차수 : 정점과 연결된 간선의 개수, in-degree와 out-degree가 다르다

 

§ 표현
그래프의 저장은 간선을 효율적으로 저장하는 것을 의미한다. 

효율 =  한 정점이 있을때, 한 정점과 연결된 간선을 찾는 시간이 빠른 것

#방법1. 1차원 배열

1차원 배열은 효율성이 떨어짐. 전체 간선을 다 살펴봐야 함. O(E)

#방법2. 인접행렬

이차원 배열 A[i][j]

i와 j가 연결되어 있으면 A[i][j]=1. 공간 = O(V^2), 효율★=O(V)

but 인접행렬은 거의 안쓴다.

#방법3. 인접리스트.

A[i] = i와 연결된 모든 정점을 저장 (리스트, 배열)

왜 리스트냐, 몇개를 저장해야할 지 알 수 없기 때문에, 크기를 모른다.

크기가 변하는 배열을 쓰면 된다.

C++ : vector / Java : ArrayList / Python은 원래 변함

인접리스트 효율 = O(E), 공간 = E

가중치가 필요하면 두개씩 넣으면 된다.

-------------------------------------------------

+간선리스트라는 자료구조도 있다. 

아주 특수한 상황에서만 쓰인다.

크기가 변하는 배열을 쓸 수 없을때 링크드 리스트를 구현해야 하는데 구현하기 싫을때, 한 정점과 연결되어있는 간선을 빠르게 알 수 있다. 

단점 : 정렬을 한번 해야한다. 만드는데 걸리는 시간 O(ElogE)

 

§ 탐색

목적 : 한 정점에서 시작해 연결되어 있는 모든 정점을 1번씩 방문

종류 : DFS(깊이우선), BFS(너비우선, 최단경로(가중치가 모두 1일때)) - 차이점은 방문순서

중요도 : BFS >>>> DFS

저작자표시 비영리 변경금지

'공부 > 백준 2020년 1~2월 알고리즘' 카테고리의 다른 글

6번째 수업  (0) 2020.01.23
5번째 수업  (0) 2020.01.22
3번째 수업  (0) 2020.01.15
2번째 수업  (0) 2020.01.11
1번째 수업 복습  (0) 2020.01.08
    '공부/백준 2020년 1~2월 알고리즘' 카테고리의 다른 글
    • 6번째 수업
    • 5번째 수업
    • 3번째 수업
    • 2번째 수업
    Lai_Khan
    Lai_Khan

    티스토리툴바