Skip to content

Commit 031c52d

Browse files
committed
[손재영] level2 배달 풀이 및 주석
1 parent 4b08759 commit 031c52d

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

level-2/배달.js

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

0 commit comments

Comments
 (0)