File tree Expand file tree Collapse file tree 4 files changed +192
-0
lines changed
non-overlapping-intervals
number-of-connected-components-in-an-undirected-graph
remove-nth-node-from-end-of-list Expand file tree Collapse file tree 4 files changed +192
-0
lines changed Original file line number Diff line number Diff line change
1
+ """
2
+ 구간이 겹쳐 삭제해야 되는 최소 구간의 수를 반환해라
3
+ -> Greedy
4
+ -> '겹치지 않게 최대한 많은 구간을 남기고, 나머지를 제거'
5
+
6
+ 문제 풀이
7
+ 1. 끝나는 시간 기준으로 오름차순 정렬
8
+ 2. 이전 구간의 끝과 현재 구간의 시작을 비교
9
+ 3. 겹치면 현재 구간을 제거
10
+
11
+ TC: O(n log n), 정렬 O(n log n) + 모든 interval 한 번씩 순회 O(n)
12
+ SC: O(1)
13
+ """
14
+
15
+ from typing import List
16
+
17
+ class Solution :
18
+ def eraseOverlapIntervals (self , intervals : List [List [int ]]) -> int :
19
+ # 끝나는 시간이 빠른 순으로 정렬
20
+ # -> 일찍 끝나는 구간을 선택하면, 이후에 더 많은 구간을 넣을 수 있는 여지가 커짐!
21
+ intervals .sort (key = lambda x : x [1 ])
22
+
23
+ # 첫 구간 선택
24
+ prev_end = float ('-inf' ) # 음의 무한대로 비교의 기준값 가장 작게 설정 -> 첫 번째 구간 무조건 선택됨
25
+ count = 0
26
+
27
+ # 하나씩 검사
28
+ for start , end in intervals :
29
+ if start >= prev_end :
30
+ # 겹치지 않음 -> 그대로 유지
31
+ prev_end = end
32
+ else :
33
+ # 겹침 -> 하나 제거
34
+ count += 1
35
+
36
+ return count
Original file line number Diff line number Diff line change
1
+ /**
2
+ * TC: O(N + E), N: 노드의 개수, E: 간선의 개수
3
+ * SC: O(N + E)
4
+ */
5
+
6
+ // DFS
7
+ function countComponentsDFS ( n : number , edges : number [ ] [ ] ) : number {
8
+ const graph : number [ ] [ ] = Array . from ( { length : n } , ( ) => [ ] ) ;
9
+
10
+ // 그래프 초기화
11
+ for ( const [ u , v ] of edges ) {
12
+ graph [ u ] . push ( v ) ;
13
+ graph [ v ] . push ( u ) ;
14
+ }
15
+
16
+ const visited = new Set < number > ( ) ;
17
+
18
+ function dfs ( node : number ) {
19
+ visited . add ( node ) ;
20
+ for ( const neighbor of graph [ node ] ) {
21
+ if ( ! visited . has ( neighbor ) ) {
22
+ dfs ( neighbor ) ;
23
+ }
24
+ }
25
+ }
26
+
27
+ let components = 0 ;
28
+ for ( let i = 0 ; i < n ; i ++ ) {
29
+ if ( ! visited . has ( i ) ) {
30
+ components ++ ;
31
+ dfs ( i ) ;
32
+ }
33
+ }
34
+
35
+ return components ;
36
+ }
37
+
38
+ // BFS
39
+ function countComponentsBFS ( n : number , edges : number [ ] [ ] ) : number {
40
+ const graph : number [ ] [ ] = Array . from ( { length : n } , ( ) => [ ] ) ;
41
+
42
+ // 그래프 초기화
43
+ for ( const [ u , v ] of edges ) {
44
+ graph [ u ] . push ( v ) ;
45
+ graph [ v ] . push ( u ) ;
46
+ }
47
+
48
+ const visited = new Set < number > ( ) ;
49
+ let components = 0 ;
50
+
51
+ for ( let i = 0 ; i < n ; i ++ ) {
52
+ if ( ! visited . has ( i ) ) {
53
+ components ++ ;
54
+ const queue : number [ ] = [ i ] ;
55
+
56
+ while ( queue . length > 0 ) {
57
+ const node = queue . shift ( ) ;
58
+ if ( node === undefined ) continue ;
59
+ if ( visited . has ( node ) ) continue ;
60
+ visited . add ( node ) ;
61
+
62
+ for ( const neighbor of graph [ node ] ) {
63
+ if ( ! visited . has ( neighbor ) ) queue . push ( neighbor ) ;
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ return components ;
70
+ }
Original file line number Diff line number Diff line change
1
+ """
2
+ 뒤에서 n번째 노드를 없애고, linked list head를 반환해라
3
+ TC: O(N), 리스트 한 번 순회
4
+ SC: O(1), 포인터 2개만 사용
5
+ """
6
+
7
+ from typing import Optional
8
+
9
+ # Definition for singly-linked list.
10
+ class ListNode :
11
+ def __init__ (self , val = 0 , next = None ):
12
+ self .val = val
13
+ self .next = next
14
+
15
+
16
+ class Solution :
17
+ def removeNthFromEnd (self , head : Optional [ListNode ], n : int ) -> Optional [ListNode ]:
18
+ # dummy node를 head 앞에 두어 edge case(head 삭제 등) 처리
19
+ dummy = ListNode (0 , head )
20
+ first = dummy
21
+ second = dummy
22
+
23
+ # first를 n+1칸 먼저 이동 -> 두 포인터 사이 간격이 n
24
+ for _ in range (n + 1 ):
25
+ first = first .next
26
+
27
+ # first가 끝에 도달할 때까지 두 포인터 함께 전진
28
+ while first :
29
+ first = first .next
30
+ second = second .next
31
+
32
+ # second의 다음 노드가 삭제 대상이므로 연결 건너뛰기
33
+ second .next = second .next .next
34
+
35
+ # 실제 head는 dummy.next에 있음
36
+ return dummy .next
Original file line number Diff line number Diff line change
1
+ from typing import Optional
2
+
3
+ # Definition for a binary tree node.
4
+ class TreeNode :
5
+ def __init__ (self , val = 0 , left = None , right = None ):
6
+ self .val = val
7
+ self .left = left
8
+ self .right = right
9
+
10
+ """
11
+ 재귀 풀아
12
+ TC: O(N), 양 트리의 각 노드를 상대로 재귀함수를 딱 1번씩만 호출하기 때문
13
+ SC: O(N), 공간복잡도 = 콜스택의 최대 높이(노드의 수)
14
+ """
15
+ class Solution :
16
+ def isSameTree (self , p : Optional [TreeNode ], q : Optional [TreeNode ]) -> bool :
17
+ # 둘 다 null이면 True 반환
18
+ if not p and not q :
19
+ return True
20
+ # 둘 중 하나면 null이면 False 반환
21
+ if not p or not q :
22
+ return False
23
+ # val이 서로 다르면 탐색 중단, False 반환
24
+ if p .val != q .val :
25
+ return False
26
+ # 현재 node의 val이 같다면, 좌우측 자식 트리도 같은지 확인 -> 재귀 호출
27
+ return self .isSameTree (p .left , q .left ) and self .isSameTree (p .right , q .right )
28
+
29
+
30
+ """
31
+ 스택 풀이
32
+ TC: O(N)
33
+ SC: O(N)
34
+ """
35
+
36
+ class Solution :
37
+ def isSameTree (self , p : Optional [TreeNode ], q : Optional [TreeNode ]) -> bool :
38
+ stack = [(p , q )]
39
+
40
+ while stack :
41
+ p , q = stack .pop ()
42
+ if not p and not q :
43
+ continue
44
+ if not p or not q :
45
+ return False
46
+ if p .val != q .val :
47
+ return False
48
+ stack .append ((p .left , q .left ))
49
+ stack .append ((p .right , q .right ))
50
+ return True
You can’t perform that action at this time.
0 commit comments