From a49cb9c41dc9465d60a872aa1f28cee8566ae464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=8B=E1=85=A7=E1=86=AB=E1=84=89?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 27 Jan 2025 15:40:28 +0900 Subject: [PATCH 1/3] number of 1 bits --- number-of-1-bits/EcoFriendlyAppleSu.kt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 number-of-1-bits/EcoFriendlyAppleSu.kt diff --git a/number-of-1-bits/EcoFriendlyAppleSu.kt b/number-of-1-bits/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..2fb1a97a5 --- /dev/null +++ b/number-of-1-bits/EcoFriendlyAppleSu.kt @@ -0,0 +1,22 @@ +package leetcode_study + +// +/* +* 주어진 양의 정수(n)를 이진수로 변환했을 때, 1의 개수를 구하는 문제 (1 <= n <= 2^31 -1. 즉, 양의 정수) +* _> 숫자가 Decimal로 주어지더라도 bit 연산에서는 내부적으로 binary 로 변환하여 처리됩니다. +* 시간 복잡도: O(1) +* -> masking 연산은 항상 32번 고정이기 때문에 상수 시간 복잡도 +* 공간 복잡도: O(1) +* -> 추가적인 메모리 사용 없이 두 개의 변수 count, mask만 사용되기 때문에 상수 공간 복잡도 +* */ +fun hammingWeight(n: Int): Int { + var count = 0 + var mask = 1 shl 31 + while (mask != 0) { + if (n and mask != 0) { + count++ + } + mask = mask ushr 1 + } + return count +} From 2379b4268ef04607c5c36e715d403ea0d990eb4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=8B=E1=85=A7=E1=86=AB=E1=84=89?= =?UTF-8?q?=E1=85=AE?= Date: Sat, 1 Feb 2025 00:22:45 +0900 Subject: [PATCH 2/3] longest repeating character replacement --- .../EcoFriendlyAppleSu.kt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 longest-repeating-character-replacement/EcoFriendlyAppleSu.kt diff --git a/longest-repeating-character-replacement/EcoFriendlyAppleSu.kt b/longest-repeating-character-replacement/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..f53394bd5 --- /dev/null +++ b/longest-repeating-character-replacement/EcoFriendlyAppleSu.kt @@ -0,0 +1,31 @@ +package leetcode_study + +/* +* 문제를 해결에 @Dale 님의 설명 참고. Sliding Window 기법을 통해 문자열 처리 +* 시간 복잡도: O(n) +* -> 주어진 문자열을 순회하면서 문자열 처리: O(n) +* -> 문자의 빈도 갱신 연산: O(1) +* +* 공간 복잡도: O(1) +* -> 문자의 개수를 저장하는데 Map 자료구조 사용. 최대 26개의 대문자 저장 공간 필요: O(1) +* */ +fun characterReplacement(s: String, k: Int): Int { + var maxLen = 0 + val counter = mutableMapOf() + var start = 0 + + for (end in s.indices) { + counter[s[end]] = counter.getOrDefault(s[end], 0) + 1 // character mapping + + // 부분 문자열의 길이에서 가장 많이 들어있는 글자의 수를 뺀 값이 k보다 클 경우 시작(start) 포인터를 이동 + // k 만큼 변경했을 때, 연속할 수 있는 문자를 만들 수 있도록 조정 + while (end - start + 1 - (counter.values.maxOrNull() ?: 0) > k) { + counter[s[start]] = counter.getOrDefault(s[start], 0) - 1 + start++ + } + + // 탐색한 부분 문자열 중 가장 긴 문자열의 값을 저장 + maxLen = maxOf(maxLen, end - start + 1) + } + return maxLen +} From afe32506a4ed139c482cd62a75d58c0859be2bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=8B=E1=85=A7=E1=86=AB=E1=84=89?= =?UTF-8?q?=E1=85=AE?= Date: Sat, 1 Feb 2025 01:16:09 +0900 Subject: [PATCH 3/3] clone graph --- clone-graph/EcoFriendlyAppleSu.kt | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 clone-graph/EcoFriendlyAppleSu.kt diff --git a/clone-graph/EcoFriendlyAppleSu.kt b/clone-graph/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..ae1157555 --- /dev/null +++ b/clone-graph/EcoFriendlyAppleSu.kt @@ -0,0 +1,47 @@ +package leetcode_study + +/* +* Graph Node 복사 문제 +* queue를 사용해 문제 해결 +* 새로 생성한 Node에 대해 방문처리를 하지 않을 경우 무한 Loop에 빠지게됨 -> 각 노드가 양방향을 가리키고 있기 때문. +* 따라서, Map 자료구조를 사용해 Map<기존 Node, 복사 Node>의 모습으로 Key-Value 쌍으로 방문처리를 표현 +* +* 시간 복잡도: O(n) +* -> graph의 Node를 한 번씩 방문하여 복사하는 과정: O(n) +* 공간 복잡도: +* -> 복사된 Node를 매핑하는 Map 자료구조의 크기: O(n) +* -> BFS를 사용한 queue size: O(n) +* -> 새로 생성된 Node의 neighbor list: O(n) +* */ +fun cloneGraph(node: Node?): Node? { + if (node == null) return null + if (node.neighbors.isEmpty()) return Node(1) + + // Map< 기존 Node, 복사 Node> + val nodeMap = mutableMapOf() + + val queue = ArrayDeque() + queue.add(node) + nodeMap[node] = Node(node.`val`) + + while (queue.isNotEmpty()) { + val current = queue.removeFirst() + val clonedNode = nodeMap[current]!! // 현재 노드의 복제본 + + for (neighbor in current.neighbors) { + if (neighbor == null) continue + + // 해당 이웃이 아직 복사되지 않았다면 복사하여 맵에 저장하고 큐에 추가 + if (!nodeMap.containsKey(neighbor)) { + nodeMap[neighbor] = Node(neighbor.`val`) + queue.add(neighbor) + } + + // 복제된 현재 노드의 이웃 리스트에 복제된 이웃 노드를 추가 + // 양방향을 따질 필요 없이 내부 neighbor node list에 모든 노드가 있음 + clonedNode.neighbors.add(nodeMap[neighbor]) + } + } + return nodeMap[node] +} +