Ref : https://github.com/neity16/tech-interview-for-developer
- 동작
인접한 인자
와비교
하여더 큰 원소
를뒤
로 보내는정렬 방식
시간복잡도
=O(N^2)
공간복잡도
=O(N)
-->추가로 공간을 필요로하지는 않고
기존 배열만큼만 사용
- 동작
현재 자리
에현재 차례에 해당하는 가장 작은 값
을 가져와서정렬
시간복잡도
=O(N^2)
공간복잡도
=O(N)
- 동작
2번째 원소
부터시작
해서그 앞 원소들
과비교
해서삽입할 위치
를 정한 후선택된 위치
에원소
를삽입
하는 정렬선택정렬
과유사
하지만최선의 경우
O(N)
이라는 효율성을 가짐시간복잡도 O(N^2)
/최선의 경우 O(N)
공간복잡도 O(N)
- 동작
1)피벗
을선택
한 후
2)오른쪽
에서는왼쪽
으로이동
하면서피벗보다 작은 수
를찾는다
3)왼쪽
에서는오른쪽
으로이동
하면서피벗보다 큰 수
를찾는다
4)2,3번
에서 찾은두 수를 교환
한다.
5)2~4
를더 이상 진행할 수 없을 때 까지
반복
하고엇갈린 자리중 작은값
을피벗
과자리 교환
6)결과적
으로피벗
을중심
으로왼쪽은 피벗보다 작은수
,오른쪽은 큰 수
가정렬
됨
7)정렬된 두 집단
에서다시 피봇을 정해서 반복!
평균적
으로O(NlogN)
의시간복잡도
O(N)
의공간복잡도
분할 정복 기법
으로 동작(최악의 경우 제외
하고)가장 작거나 큰 값
을피벗
으로설정
할 경우분할되지 않아서
O(N^2)
를 가짐서로 먼 거리에 있는 요소
를교환
하면서속도를 줄일 수 있음
불안정 정렬
:같은 값
을가지는 요소
의순서
가보장되지 않음
- 동작
영역을 쪼갤 수 있을 때 까지 쪼갠 뒤
합병(merge)
하면서정렬 수행
순차적인 비교
로정렬을 진행
하므로Linked-list 정렬
이 필요할 때매우 효율적
-->삽입 삭제 연산
이O(1)
이라서효율적
(접근 연산
은O(N)
이 소요되므로퀵 정렬을 하면 비효율적
이다)퀵 정렬
과는 다르게안정 정렬
에 속함
:같은 값을 정렬
할 때순서가 보장됨
평균
,최선
,최악
모두O(NlogN)
공간복잡도
는O(N)
- 동작
1)Heapify 연산
을 통해최대 or 최소 heap구조
로변환
2)root값
을가장 마지막 원소
와교환
3)힙의 사이즈
를하나 감소
4)1~3 반복
완전 이진트리
를기본
으로하는힙(Heap) 자료구조
를기반
으로 한 정렬시간복잡도
:O(NlogN)
퀵정렬
과합병정렬
의 성능이 좋아자주 사용되지는 않는다
가장 큰 값을 구할 때 효율적
-->heapify
는O(logN)
밖에 안걸리기 때문
- 동작
모든 원소
의기본 요소(Radix)
를이용
하여정렬
을 진행
1)모든 원소
의1의 자리 수
를비교
해서 정렬
2)1의 결과를 바탕
으로10의 자리 수
를비교
해서 정렬
3)n자리수까지 비교
를반복
4)마지막 자리수까지 검사
하면정렬 완료
특정 자리수
를이용
해정렬을 진행
비교를 하지 않기 때문
에빠른 시간복잡도
를 가짐시간복잡도는 O(d*N)
/d=정렬할 숫자의 자리수
를 의미- 제한 사항
길이가 같은 원소만 비교 가능
버킷
이라는추가적인 메모리 공간이 필요
- 동작
각 숫자
가몇 번 등장
했는지 센 뒤작은 값
부터출력
하면정렬
이 된다.
- 안정 정렬
:같은 값의 순서가 보장
된다시간복잡도
:O(N)
기수정렬
과 마찬가지로비교를 하지 않기 때문
에빠른 정렬 이 가능
- 제한
정렬하는 숫자
가특정한 범위 내에 있을 때
만사용 가능
해당 숫자 범위
만큼메모리가 필요
-->낭비가 심함
- 안정 정렬
버블 정렬
삽입 정렬
병합 정렬
계수 정렬
기수 정렬
- 불안정 정렬
퀵정렬
선택 정렬
힙 정렬
개념
순서가 정해져있는 작업
을차례로 수행
해야 할 때, 그순서를 결정
해주는 알고리즘여러개의 경로
가 존재할 수 있음 -->여러개의 답
이 존재할 수 있다!- 반드시
그래프
는DAG(Directed Acyclic Graph)
여야 한다- 시간복잡도 =
O(V+E)
조건 & 구현
- DAG(
Directed Acyclic Graph
)
사이클이 존재하지 않는 방향 그래프
스택
/큐
를 이용해서 구현 가능 --> 보통은큐를 많이 사용
- 진입 차수(
indegree
)
해당 노드를 향한 방향의 수
(받는 화살표의 수
)
로직
모든 노드
의진입 차수
계산진입 차수
가0인 노드
를큐
에 삽입큐에서 꺼낸 노드
에연결된 간선
을제거
제거 후
진입 차수가 0이 된 노드
를큐
에 삽입큐가 빌 때 까지
앞 과정을반복
동적프로그래밍(DP)
이 지나치게 많은 일을 하는 것에서 착안된 알고리즘
-->DP를 보완하는 알고리즘
이다.
- 당장 눈 앞에 보이는
최적의 상황만을 쫓는 알고리즘
부분에서의 최적의 해
가전체적인 최적의 해
가 되는 경우!- 무조건 큰 경우대로 / 작은 경우대로 처럼 극단적으로 문제에 접근한다
-->정렬(sort)기법과 함께 사용되는 경우가 많다
ex) 거스름돈 주기 : 무조건 큰 화폐부터 거슬러 주면 된다 ! (최적의 해)
특정 조건
을 만족하는모든 경우의 수
에 대해 수행하는 알고리즘- 해를 찾는 도중 해가 아니어서 막히면,
되돌아가서 다시 해를 찾아가는 기법
브루트포스(완전탐색)
과유사
하지만,특정 조건을 만족하는 경우의 수
를 수행한다는 차이점이 있음- 해를 찾아가는 도중, 지금의 경로가 해가 될 것 같지 않으면 그 경로를 더이상 가지 않고 되돌아 간다
--> 이것을가지치기
한다고 한다
- 주된 사용
:DFS
등으로 모든 경우의 수를 탐색하는 과정에서,
조건문 등을 걸어서 답이 절대로 될 수 없는 상황을 정의하여
그러한 상황에서 탐색을 중지시킨 뒤 돌아가서 다른 경우를 탐색하게 한다.
예시 문제
#include <iostream> #include <vector> #include <algorithm> using namespace std; int N, M; int arr[10]; bool isused[10]; void func(int depth){ if(depth == M){ for(int i=0;i < M;i++) cout << arr[i] << ' '; cout << '\n'; return; }else{ /* 백트래킹 핵심 부분 */ for(int i=1;i<=N;i++) { if(!isused[i]){ arr[depth] = i; isused[i] = true; func(depth+1); isused[i] = false; } } } } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> N >> M; func(0); return 0; }
[ Intro ]
그래프
에서정점
끼리최단 경로
를 구하는 방법
하나의 정점 --> 다른 하나의 정점까지 최단경로
하나의 정점 --> 다른 모든 정점까지의 최단경로
Dijkstra 알고리즘
벨만-포드 알고리즘
하나의 목적지로가는 모든 최단 경로
모든 정점끼리의 최단 경로를 구하는 문제
플로이드 워셜 알고리즘
다익스트라 최단경로 알고리즘
은하나의 정점 --> 다른 모든 정점까지 최단경로
에 해당
[ 로직 ]
- 모든 노드간 이동거리 배열을
INF(큰 값)
으로 초기화출발 노드(정해짐)
를 통해 갈 수 있는경로 갱신
- 갱신된 테이블을 통해
방문하지 않은 노드
중최단거리가 가장 짧은 노드
를 선택- 노드 간 이동거리가 더짧다면
갱신
하며 수행- 다시
방문하지 않은 노드
중최단거리가 가장 짧은 노드
를 선택 후반복!
[ 설명 ]
다익스트라
가 제시안최단경로 알고리즘
현재 노드
에연결된 정점
까지최소 경로
를갱신
한 뒤,현재
를기준
으로방문하지 않은 점
들 중거리가 가장 짧은 노드
를선택
하는 알고리즘
-->한 단계
당하나의 노드
에 대한최단 거리
를 확실히 찾는다- 현재 상황에서 최선을 선택한다는 원리로
'그리디 알고리즘'
으로 분류된다간선
이음의 값
을 가지면성립되지 X
--> 이 경우벨만-포드 알고리즘
을사용
해야 한다단순 값
이 아닌경로
를 찾기 위해서는 추가적인 코드가 필요
구현 방법
에 따라시간복잡도
가 상이하다
배열
로 구현 ->O(V^2)
우선순위 큐
로 구현 ->O(ElogE)
-->O(ElogV)
(모든 간선은 한번씩 수행O(E)
+ 우선순위 큐를 통해 값을 추출O(logE)
=O(ElogE)
)
:Heap 자료구조
를 사용하면 노드를 선택하는 과정을O(N)
이 아닌O(logN)
으로 가능
(최대 힙
-> 값이큰 값
이 먼저 나옴
최소 힙
-> 값이작은 값
이 먼저 나옴)
[ 예시 & 코드 ]
priority_queue를 이용한 Dijkstra
#include <iostream> #include <vector> #include <queue> #include <algorithm> #define INF 1e9 // 10억을 의미 using namespace std; vector<pair<int,int>> graph[30001]; // 0인덱스는 사용하지 X int dis[30001]; // 0인덱스는 사용하지 X void dijkstra(int start){ priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq; pq.push({0, start}); dis[start] = 0; while(!pq.empty()) { int dist = pq.top().first; // 비용 int now = pq.top().second; // 현재 거쳐가는 지점의 인덱스 pq.pop(); if(dis[now] < dist) continue; /* i는 의미 없고 그냥 순회하기 위한 변수 */ for(int i=0;i<graph[now].size();i++) { /* first-> 목적지 , second -> 목적지 까지 필요한 비용 */ int cost = dist + graph[now][i].second; // 비용 계산 if(cost < dis[graph[now][i].first]){ // first에는 목적지가 들어가있고 현재 기록된 값이랑 비교 검사 dis[graph[now][i].first] = cost; // first까지 가는데 들어가는 비용 cost를 갱신하고 pq에 삽입 pq.push({cost, graph[now][i].first}); } } } } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int N, M, C; int cnt=0, MAX=0; cin >> N >> M >> C; fill(dis, dis+30001, INF); for(int i=0;i<M;i++) { int a,b,c; cin >> a >> b >> c; graph[a].push_back({b,c}); } dijkstra(C); for(int i=1;i<=N;i++) if(dis[i] != INF){ cnt++; MAX = max(MAX, dis[i]); } cout << cnt-1 << ' '<< MAX << '\n'; return 0; }
ref : https://ssungkang.tistory.com/entry/Algorithm-%EB%B2%A8%EB%A7%8C%ED%8F%AC%EB%93%9CBellman-Ford-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
https://victorydntmd.tistory.com/104
https://yabmoons.tistory.com/365
[ 설명 ]
한 노드
->다른 모든 노드
까지의최단경로
를계산
하는 알고리즘음수의 가중치
를 가진 경우에도최단 경로
를 구할 수 있음
(다익스트라의 한계 극복
/시간복잡도는 더 높다
)- 시간복잡도 =
O(|V||E|)
=O(V^3)
(그래프의 간선이 많으면
보통정점 개수의 제곱 정도
로 존재 /O(E)
=O(V^2)
)음의 가중치를 갖는 상황
에서순환(Cycle)
이 생기면경로가 계속 짧아
지지만, 이것은실질적인 최단 경로가 아니다
-->벨만 포드
의핵심
은순환을 포함하지 않으며
,경로의 길이
가최대 |V|-1을 가진다는 것!
- Relax 연산
해당 정점
에서더 낮은 가중치로 도달할 수 있는 경우
,그 값을 갱신
해 주는 과정
(모든 정점
중한 번이라도 계산된 정점
에연결된 간선
을 통해갱신
수행!)
- 음의 Cycle 검사
Relax연산
을V(N-1)
까지 수행하면최단 거리가 나오도록 설계
가 되어있다- 만약
V(N)에 대해 Relax연산
을 수행했는데최단 경로가 갱신
되면음의 Cycle인 경우라고 판단 가능!
[ 로직 ]
출발 정점(V1)
의 거리는0
/다른 정점
까지 거리는INF
로 초기화모든 정점(V1 ~ VN)
중한 번이라도 계산된 정점
에 대해서만연결된 간선
을 통해최소 경로
인 경우갱신
한 번이라도 계산된 정점
(dist가 INF가 아닌 정점
)만 선택해야 하는 이유!
-->한번도 경유하지 않은 점
은 거쳐서갈 수 없기 때문에
간선의 비용이 짧아도 유효하지 X
출발 정점
을V2 ~ VN
까지확장
해서앞 과정을 반복!
--> 즉,V1 ~ V(N-1)까지
각Relax 연산
을 수행
--> 하지만, 보통음의 Cycle
을검사
하기 위해V(N)
까지 수행
[ 코드 ]
#include <iostream> #include <vector> using namespace std; #define INF 987654321 int dist[502]; vector<pair<int,int>> v[502]; int main(){ ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); // 정점,간선의 수 int N,M; cin >> N >> M; bool cycle = false; for (int i=0;i<M;i++){ int node1,node2,w; cin >> node1 >> node2 >> w; v[node1].push_back(make_pair(node2, w)); } for (int i=1;i<=N;i++){ dist[i] = INF; } dist[1] = 0; // 경로의 길이는 N-1 이고 N 이 된다면 음수사이클 생긴다. for (int i=1;i<=N;i++){ // 모든 정점에 대해서 모든 간선을 탐색한다. for (int j=1;j<=N;j++){ for (auto &n : v[j]){ // 방문되지 않은 지점에서 출발은 SKIP if (dist[j] != INF && dist[n.first]>n.second + dist[j]){ dist[n.first] = n.second + dist[j]; if (i==N) cycle = true; } } } } if (cycle) cout << "-1\n"; else { for (int i=2;i<=N;i++){ if (dist[i] == INF) cout << "-1\n"; else cout << dist[i] << "\n"; } } }
[ 설명 ]
모든 노드 -> 다른 모든 노드
까지의최단경로 모두 계산
하는 알고리즘다익스트라 알고리즘
과 마찬가지로거쳐가는 노드
를기준
으로 알고리즘을 수행2차원 배열
을 통해모든 노드
간최단거리
를 기록2차원 테이블 배열
을점화식
에 따라갱신
한다는 점에서DP
에 속함
: 점화식에 맞게 배열을 갱신한다
시간복잡도
가 무조건O(V^3)
이기 때문에플로이드 워셜
을 쓰는 문제의입력
은500
을 넘지 않게 주어진다
[ 코드 ]
#include <iostream> #include <vector> #include <queue> #include <algorithm> #define INF 1e9 // 10억을 의미 using namespace std; int graph[501][501]; int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int N,M; cin >> N >> M; /* 최단거리 테이블을 모두 무한으로 초기화 */ for(int i=0;i<501;i++) fill(graph[i], graph[i]+501, INF); /* 자기 자신으로 가는 비용은 0으로 초기화 */ for(int a=1;a<=N;a++) for(int b=1;b<=N;b++) if(a==b) graph[a][b] = 0; for(int k=1;k<=N;k++) { for(int a=1;a<=N;a++) { for(int b=1;b<=N;b++) /* a-> 출발노드, b-> 도착노드 , k-> 경유 노드 */ graph[a][b] = min(graph[a][b], graph[a][k]+graph[k][b]); } } /* 수행된 결과를 출력 */ for(int a=1;a<=N;a++) { for(int b=1;b<=N;b++) { if(graph[a][b] == INF) cout << "INF" << ' '; else cout << graph[a][b] << ' '; } cout << '\n'; } return 0; }
3중 for
문을 통해 각 모든 점에 대해기존 경로
vs경유 경로
를 검사해서 작은 경로로 update!구현 난이도
는Dijkstra
보다낮다
[ 필요 지식 ]
- 신장 트리(
Spanning Tree
)
그래프
에서모든 노드를 포함
하면서사이클이 존재하지 않는
부분 그래프(무향 그래프)
(모든노드 포함
+사이클 X
)
- 최소 신장 트리 (
MST
=Minimum Spanning Tree
)
최소한의 비용
으로구성
되는신장 트리
[ 설명 ]
최소 신장 트리
를 구하는알고리즘 중 하나
(MST
를 구하는다른 알고리즘
으로프림(Prim) 알고리즘
이 있음 )
Union-Find 알고리즘
이 사용
Union
:두 집합을 합치는 연산
- 최초
모든 노드
는parent
로자기 자신
을 가지고 있다두개의 노드
중더 큰 번호에 해당하는 노드
의부모노드
를작은 노드
로갱신!
Find
:연결된 루트 노드를 찾는 것
(여기서는부모 노드
를 찾는 것)
- 재귀적으로 구현하여 연결된 가장 부모 노드를 찾는다
-->findParent 구현시
부모 테이블 값
을바로 갱신
하면'경로 압축'
이 가능함!
- 크루스칼(
Kruskal
) 알고리즘로직
1)모든 간선
에 대해오름차순 정렬
2)아직 처리하지 않은 간선
중가장 짧은 간선
을선택
3)사이클이 없으면
(부모 노드가 같지 않으면
)현재 MST
에추가
(사이클이 있으면
제외
)
[ 코드 ]
#include <iostream> #include <vector> #include <algorithm> using namespace std; int N,M,ans,max_cost; int parent[100002]; // 1~100000 사용 /* find 연산 */ int findParent(int x){ if(x == parent[x]) return x; return parent[x] = findParent(parent[x]); } /* union 연산 */ void unionParent(int a, int b){ a = findParent(a); b = findParent(b); if(a<b) parent[b] = a; else parent[a] = b; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> N >> M; vector<pair<int, pair<int,int>>> edges; for(int i=0;i<M;i++) { int a, b, cost; cin >> a >> b >> cost; edges.push_back({cost,{a,b}}); } // parent 초기화 for(int i=1;i<=N;i++) parent[i] = i; // edges 정렬 sort(edges.begin(), edges.end()); for(int i=0;i<edges.size();i++) { int a = edges[i].second.first; int b = edges[i].second.second; int cost = edges[i].first; if(findParent(a) != findParent(b)){ unionParent(a,b); max_cost = max(max_cost, cost); ans += cost; } } cout << ans - max_cost; return 0; }
findParent
find 연산
return parent[x] = findParent(parent[x]);
를 통해서경로 압축
을바로 구현
-->바로 위 부모가 아니라
루트
를 가리킬 수 있도록바로바로 갱신!
findUnion
:union 연산
parent 초기화
edges 정렬
MST 추가
짧은 cost 순서
대로사이클이 형성하지 않으면
현재 MST
에추가
ref :
https://www.weeklyps.com/entry/%ED%94%84%EB%A6%BC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Prims-algorithm
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=kimmy5000&logNo=220635475967
개념
무향 연결 그래프
가 주어질 때,MST
를 구하는 알고리즘크루스칼(Kruskal)
알고리즘과목적이 같으나
,로직이 다름
프림은 정점(V) 위주
/크루스칼은 간선(E) 위주
로직
임의의 정점
을 선택하여T에 추가
(T는 트리
)T에 있는 노드
와T에 없는 노드
사이의간선
중가중치가 최소인 간선
을 찾는다
(트리에 있는 노드
와,없는 노드
사이간선
중최소
를 구하기에따로 Cycle 검사 로직이 필요 없음)
찾은 간선이 연결하는 노드
중T에 없는 노드
를T에 추가
모든 노드
가T에 포함될 때 까지
앞 과정반복
크루스칼(Kruskal) 알고리즘과 차이점
- 로직
- 프림(
Prim
) :정점을 선택
하고그것과 연결된 가장 적은 비용의 간선
을 선택하는 방식- 크루스칼(
Kruskal
) :모든 간선의 비용중
적은 비용의 간선
을선택
하는 방식
- 구성 방식
- 프림(
Prim
) :정점들이 계속 연결
되는 방식- 크루스칼(
Kruskal
) :서로 다른 정점들의 집합
이합쳐지는
방식
- 시간복잡도(
Time Complexity
) /E=간선의 수
,V=정점의 수
- 프림(
Prim
)
- unsorted array로 구현 :
O(V^2)
- priority queue로 구현 :
O(ElogV)
- 크루스칼(
Kruskal
) :O(ElogV)
[ 설명 ]
정렬된 상태
에서 원소를O(logN)
의 시간복잡도로 찾는탐색
- 주로
파라메트릭 서치
유형 문제 풀이로 많이 사용됨
입력의 크기
가매우 큰 상황
에서일정 조건
으로탐색
을 해야하면이진탐색
을 가장먼저 떠올려야 한다
특정 수
의개수
를 구하는 과정을O(logN)
으로 수행할 수 있음
C++
에서upper_bound
와lower_bound
를 이용해countByRange
를 정의한 후leftValue
와 ```rightValue
에 같은 값을 넣으면특정 수의 개수
를 구할 수 있음
C++ STL
에binary_search()
가 구현되어 있으나 지정 값을 찾는기능에 제한된다/* stl container */ binary_search(arr.begin(), arr.end(), M); /* array */ binary_search(arr, arr+N, M);
[ 코드 - 반복문을 통한 이진탐색 구현 ]
#include <cstdio> #include <vector> #include <queue> #include <iostream> #include <cmath> #include <algorithm> #define ll long long using namespace std; ll N,M,high; vector<ll> arr(1000002); /* 이진탐색 - O(logN) */ void bs(vector<ll>& arr, ll st, ll en){ ll ans=0; while(st <= en) { ll tot=0; ll mid = (st + en)/2; for(auto a : arr) if(a > mid) tot += a-mid; if(tot < M) en = mid-1; else{ ans = mid; st = mid + 1; } } cout << ans; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> N >> M; for(int i=0;i<N;i++) { cin >> arr[i]; high=max(high,arr[i]); } bs(arr,0,high); return 0; }
[ 설명 ]
두 집단 사이
에서Max Matching되는 경우
를구하는 것
노트북 집단
과사람 집단
에서최대로 연결될 수 있는 경우
를 구하는 것- 핵심
:내가 선택하려는 노드
가이미 선택
되어 있을 때
그것을 선택한 노드
에게다른 노드를 선택할 수 있도록 권장
하는 것
[ 예시 코드 ]
#include <cstdio> #include <vector> #include <queue> #include <iostream> #include <cmath> #include <algorithm> #include <set> #define ll long long using namespace std; vector<pair<int,int>> v(1010); int work[1010]; bool finish[1010]; int T, N, M; /* 이분 탐색 */ bool DFS(int x){ for(int t=v[x].first;t<=v[x].second;t++) { if(finish[t]) continue; finish[t] = true; if(work[t] == -1 || DFS(work[t])){ work[t] = x; return true; } } return false; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> T; while(T--) { v.clear(); cin >> N >> M; for(int i=0;i<M;i++) { int a, b; cin >> a >> b; v.push_back({a,b}); } /* 연결된 점의 좌표 초기화 */ fill(work, work+1010, -1); int ans=0; /* 모든 점들에 대해 연결 */ for(int i=0;i<M;i++) { /* 정점 방문 여부 초기화 */ fill(finish, finish+1010, false); if(DFS(i)) ans++; } cout << ans << '\n'; } return 0; }
- BOJ 9576
[ DFS ]
그래프의 탐색 방법
의한 종류
깊이를 우선
으로갈 수 있는 만큼 최대한 탐색
한 뒤더 이상 갈 수 없다면
이전 정점으로 돌아가는 방식
- 구현
stack 사용
재귀(recursive)
시간복잡도
(V=정점의 수
/E=간선의 수
)
그래프를 인접 행렬
로 표현 -->O(V^2)
그래프를 인접 리스트
로 표현 -->O(V+E)
[ BFS ]
그래프의 탐색 방법
의한 종류
넓이를 우선
으로순차적으로 인접한 노드
부터탐색
하는 방법- 구현
큐(queue)
를 통한 구현시간복잡도
(V=정점의 수
/E=간선의 수
)
그래프를 인접 행렬
로 표현 -->O(V^2)
그래프를 인접 리스트
로 표현 -->O(V+E)