Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions clone-graph/yhkee0404.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import scala.collection.mutable.ListBuffer

/**
* Definition for a Node.
* class Node(var _value: Int) {
* var value: Int = _value
* var neighbors: List[Node] = List()
* }
*/

object Solution {
def cloneGraph(graph: Node): Node = {
if (graph == null) {
return null
}
val dp = Array.fill[Node](101)(null)
cloneGraph(dp, graph)
}
def cloneGraph(dp: Array[Node], graph: Node): Node = {
if (dp(graph.value) != null) {
return dp(graph.value)
}
val u = Node(graph.value)
dp(graph.value) = u
val neighbors = ListBuffer[Node]()
graph.neighbors
.foreach {
neighbors += cloneGraph(dp, _)
}
u.neighbors ++= neighbors
u
}
}
14 changes: 14 additions & 0 deletions longest-common-subsequence/yhkee0404.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Solution {
int longestCommonSubsequence(String text1, String text2) {
final dp = List.generate(
text1.length + 1,
(_) => List.filled(text2.length + 1, 0),
);
for (int i = 1; i <= text1.length; i++) {
for (int j = 1; j <= text2.length; j++) {
dp[i][j] = text1[i - 1] == text2[j - 1] ? dp[i - 1][j - 1] + 1 : max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[text1.length][text2.length];
}
}
27 changes: 27 additions & 0 deletions longest-repeating-character-replacement/yhkee0404.kt
Copy link
Contributor Author

@yhkee0404 yhkee0404 Sep 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dijkstra처럼 우선순위 큐와 Cache Validation을 이용한 O(nlogn) 풀이입니다.
n <= 10^5이므로 nlogn < 26n입니다.
선형 풀이와의 비교: 2bb561c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

알고달레에서 감사하게도 선형 풀이를 배웠습니다.
다만 해당 풀이에서 Sliding Window의 끝점을 기준으로 시작점을 줄이는 것과 달리 저는 시작점을 기준으로 끝점을 늘려 봤습니다.
한편 해당 풀이 관련 개선점도 공유합니다: DaleSeo/AlgoDale#31
O(nlogn) 풀이와의 비교: 2bb561c

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
fun characterReplacement(s: String, k: Int): Int {
val cnts = MutableList<Int>('Z'.code - 'A'.code + 1) {0}
var max_cnt = 0
var ans = 0
var i = 0
var j = 0
while (j != s.length) { // T(n) = S(n) = O(n)
while (j != s.length) {
val diff = j - i - max_cnt
if (diff > k) {
break
}
val d = s[j].code - 'A'.code
if (diff == k && max_cnt != cnts[d]) {
break
}
j++
max_cnt = maxOf(max_cnt, ++cnts[d])
}
ans = maxOf(ans, j - i)
val d = s[i++].code - 'A'.code
cnts[d]--
}
return ans
}
}
38 changes: 38 additions & 0 deletions palindromic-substrings/yhkee0404.go
Copy link
Contributor Author

@yhkee0404 yhkee0404 Sep 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

부분 문자열 중 모든 Palindrome을 선형 시간에 구하는 Manacher's Algorithm입니다. 동일한 Palindrome이 중복 등장할 때는 DP를 통해 재사용합니다.
길이가 짝수인 Palindrome도 마치 길이가 홀수인 것처럼 처리할 수 있도록 Sentinel 값을 이용합니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
func countSubstrings(s string) int {
runes := []rune{} // S(n) = O(n)
for _, c := range s {
runes = append(runes, c)
runes = append(runes, '\000')
}
ans := 0
dp := make([]int, len(runes) - 1)
lastR := -1
lastMid := -1
i := 0
for i != len(dp) { // Manacher T(n) = O(n)
diff := lastR - i
deviation := 0
if diff > 0 {
deviation = min(diff, dp[lastMid - (i - lastMid)])
}
l := i - deviation
r := i + deviation
for l != 0 && r + 1 != len(dp) && runes[l - 1] == runes[r + 1] {
deviation++
l--
r++
}
dp[i] = deviation
if r > lastR {
lastR = r
lastMid = i
}
if runes[i] == '\000' {
ans += (deviation + 1) >> 1
} else {
ans += 1 + (deviation >> 1)
}
i++
}
return ans
}
31 changes: 31 additions & 0 deletions reverse-bits/yhkee0404.rs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 << 6 = 64개 만큼의 전처리 시간과 공간을 희생해서 추론 시간을 32번에서 6번으로 줄였습니다.
Bucket 또는 Square Root Decomposition이라고 할 수 있겠어요: https://github.com/DaleStudy/leetcode-study/pull/1792/files#r2265196896

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::sync::OnceLock;

static _TABLE: OnceLock<Vec<i32>> = OnceLock::new();

impl Solution {

pub fn reverse_bits(mut n: i32) -> i32 {
let mut x = 0;
for i in 0..6 {
let shift = if i == 5 {2} else {6};
x = x << shift | Self::init_table()[(n & (1 << shift) - 1) as usize] >> 6 - shift;
n >>= 6;
}
x as i32
}

fn init_table() -> &'static Vec<i32> {
_TABLE.get_or_init(|| {
let mut table: Vec<i32> = vec![0; 1 << 6];
for (i, x) in table.iter_mut().enumerate() {
let mut j = i as i32;
for k in 0..6 {
*x = *x << 1 | j & 1;
j >>= 1;
}
}
table
})
}

}