Skip to content

Commit 9a020a1

Browse files
Merge pull request #76 from pereng11/jaeyeong
[손재영] level2 배달 풀이 및 주석
2 parents 1ae2b59 + f16e1fe commit 9a020a1

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

level-2/배달.js

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
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

Comments
 (0)