1
+ //https://github.com/codeisneverodd/programmers-coding-test
2
+ //완벽한 정답이 아닙니다.
3
+
4
+ //정답 1 - pereng11
5
+ // 다익스트라 + 최소힙 O( N * logN )
6
+ // [목적지, 거리] 노드를 값으로 가지는, 거리에 대한 최소힙
7
+ class MinHeap {
8
+ constructor ( )
9
+ {
10
+ this . heap = [ null ] ;
11
+ }
12
+ // 맨 끝에 노드를 삽입 후 위로 올라가면서 정렬
13
+ push ( val )
14
+ {
15
+ this . heap . push ( val ) ;
16
+ let childIdx = this . heap . length - 1 ;
17
+ let parentIdx = Math . floor ( childIdx / 2 ) ;
18
+ while ( parentIdx > 0 && this . heap [ parentIdx ] [ 1 ] > this . heap [ childIdx ] [ 1 ] ) {
19
+ this . swap ( childIdx , parentIdx ) ;
20
+ childIdx = parentIdx ;
21
+ parentIdx = Math . floor ( childIdx / 2 ) ;
22
+ }
23
+ }
24
+ pop ( )
25
+ {
26
+ if ( this . heap . length === 1 )
27
+ {
28
+ return undefined ;
29
+ }
30
+ // 최소값은 빼두었다가 리턴하고, 가장 끝 값을 맨 위로 가져와 아래로 내려가면서 정렬
31
+ const minNode = this . heap [ 1 ] ;
32
+ this . heap [ 1 ] = this . heap [ this . heap . length - 1 ] ;
33
+ this . heap . pop ( ) ;
34
+ let parentIdx = 1 ;
35
+ let leftChildIdx = 2 ;
36
+ let rightChildIdx = 3 ;
37
+ while ( parentIdx < this . heap . length )
38
+ {
39
+ // 자식이 없는 경우
40
+ if ( ! this . heap [ leftChildIdx ] )
41
+ {
42
+ break ;
43
+ } // 왼쪽 자식만 있는 경우
44
+ else if ( ! this . heap [ rightChildIdx ] )
45
+ {
46
+ if ( this . heap [ parentIdx ] [ 1 ] > this . heap [ leftChildIdx ] [ 1 ] )
47
+ {
48
+ this . swap ( parentIdx , leftChildIdx ) ;
49
+ }
50
+ break ;
51
+ // 둘 중 하나가 부모보다 작을 때, 더 작은 쪽으로 정렬
52
+ } else if ( this . heap [ parentIdx ] [ 1 ] > this . heap [ leftChildIdx ] [ 1 ] || this . heap [ parentIdx ] [ 1 ] > this . heap [ rightChildIdx ] [ 1 ] )
53
+ {
54
+ const minChildIdx = this . heap [ leftChildIdx ] [ 1 ] < this . heap [ rightChildIdx ] [ 1 ] ? leftChildIdx : rightChildIdx ;
55
+ this . swap ( parentIdx , minChildIdx ) ;
56
+ parentIdx = minChildIdx ;
57
+ leftChildIdx = parentIdx * 2
58
+ rightChildIdx = parentIdx * 2 + 1 ;
59
+ } else
60
+ {
61
+ // 끝까지 내려가지 않았더라도 부모가 가장 작으면 정렬 중지
62
+ break ;
63
+ }
64
+ }
65
+ return minNode ;
66
+ }
67
+ swap ( idx1 , idx2 )
68
+ {
69
+ [ this . heap [ idx1 ] , this . heap [ idx2 ] ] = [ this . heap [ idx2 ] , this . heap [ idx1 ] ] ;
70
+ }
71
+ length ( )
72
+ {
73
+ return this . heap . length ;
74
+ }
75
+ }
76
+
77
+ function solution ( N , road , K )
78
+ {
79
+ const roadsTable = { } ; //전체 도로 정보
80
+
81
+ // 도로 정보 초기화 roadTable[시작점] = [목적지, 거리] 배열
82
+ for ( let i = 1 ; i <= N ; i ++ )
83
+ {
84
+ roadsTable [ i ] = [ ] ;
85
+ }
86
+ road . forEach ( road =>
87
+ {
88
+ let [ sp , ep , dist ] = road ;
89
+ roadsTable [ sp ] . push ( [ ep , dist ] ) ;
90
+ roadsTable [ ep ] . push ( [ sp , dist ] ) ;
91
+ } ) ;
92
+
93
+ function djikstra ( sp )
94
+ {
95
+ const visited = new Array ( N + 1 ) . fill ( false ) ; //방문 확인 배열
96
+ const dist = new Array ( N + 1 ) . fill ( Infinity ) ; //목표지점까지 거리
97
+ const heap = new MinHeap ( ) ;
98
+
99
+ //시작점 삽입
100
+ heap . push ( [ sp , 0 ] ) ;
101
+
102
+ // 가장 가까운 목적지부터 순서대로 방문
103
+ while ( heap . length ( ) > 1 )
104
+ {
105
+ //힙에 저장된 목적지 중 가장 가까운 거리의 목적지를 꺼냄 [목적지, 거리]
106
+ const [ ep , val ] = heap . pop ( ) ;
107
+ //아직 방문하지 않은 곳만 처리
108
+ if ( ! visited [ ep ] )
109
+ {
110
+ //방문처리, 거리 저장
111
+ visited [ ep ] = true ;
112
+ dist [ ep ] = val ;
113
+ //방문 지점을 거쳐서 가는 다른 목적지 구하기
114
+ const nexts = roadsTable [ ep ] ;
115
+ if ( nexts )
116
+ {
117
+ nexts . forEach ( n =>
118
+ {
119
+ let [ nextEp , nextVal ] = n ;
120
+ if ( ! visited [ nextEp ] ) //아직 방문하지 않은 곳일 경우, '지금까지의 거리 + 현재 위치에서의 거리'로 힙에 삽입
121
+ {
122
+ heap . push ( [ nextEp , val + nextVal ] ) ;
123
+ }
124
+ } )
125
+ }
126
+ }
127
+ }
128
+ // 거리가 K이하인 지점의 개수 반환
129
+ const result = dist . filter ( d => d <= K ) . length ;
130
+ return result ;
131
+ }
132
+
133
+ const answer = djikstra ( 1 ) ;
134
+ return answer ;
135
+ }
136
+
137
+ //정답 2 - pereng11 O(N * N);
138
+ //다익스트라 + 선형탐색
139
+ function solution ( N , road , K )
140
+ {
141
+ const roadsTable = { } ; //전체 도로 정보
142
+
143
+ // 도로 정보 초기화 roadTable[시작점] = [목적지, 거리] 배열
144
+ for ( let i = 1 ; i <= N ; i ++ )
145
+ {
146
+ roadsTable [ i ] = [ ] ;
147
+ }
148
+ road . forEach ( road =>
149
+ {
150
+ let [ sp , ep , dist ] = road ;
151
+ roadsTable [ sp ] . push ( [ ep , dist ] ) ;
152
+ roadsTable [ ep ] . push ( [ sp , dist ] ) ;
153
+ } ) ;
154
+
155
+ function djikstra ( sp )
156
+ {
157
+ const dist = new Array ( N + 1 ) . fill ( Infinity ) ; //목표지점까지 거리
158
+ const queue = [ ] ;
159
+
160
+ queue . push ( [ sp , 0 ] ) ;
161
+
162
+ while ( queue . length > 0 )
163
+ {
164
+ const [ ep , val ] = queue . shift ( ) ;
165
+ if ( dist [ ep ] > val )
166
+ {
167
+ dist [ ep ] = val ;
168
+ const nexts = roadsTable [ ep ] ;
169
+ if ( nexts )
170
+ {
171
+ nexts . forEach ( n =>
172
+ {
173
+ let [ nextEp , nextVal ] = n ;
174
+ //거리가 더 줄어드는 경우, '지금까지의 거리 + 현재 위치에서의 거리'로 힙에 삽입
175
+ if ( dist [ nextEp ] > val + nextVal )
176
+ {
177
+ queue . push ( [ nextEp , val + nextVal ] ) ;
178
+ }
179
+ } ) ;
180
+ }
181
+ }
182
+ }
183
+ // 거리가 K이하인 지점의 개수 반환
184
+ const result = dist . filter ( d => d <= K ) . length ;
185
+ return result ;
186
+ }
187
+
188
+ const answer = djikstra ( 1 ) ;
189
+ return answer ;
190
+ }
0 commit comments