Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
63 changes: 63 additions & 0 deletions linked-list-cycle/sonjh1217.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init(_ val: Int) {
* self.val = val
* self.next = nil
* }
* }
*/

extension ListNode: Equatable {
public static func == (lhs: ListNode, rhs: ListNode) -> Bool {
return lhs === rhs
}
}

extension ListNode: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(self))
}
}

class Solution {
// O(n) time / O(n) space
func hasCycle(_ head: ListNode?) -> Bool {
var visitedNodes = Set<ListNode>()
var node = head

while node != nil {
guard let currentNode = node else {
return false
}

if visitedNodes.contains(currentNode) {
return true
}

visitedNodes.insert(currentNode)
node = currentNode.next
}
Comment on lines +31 to +42
Copy link
Contributor

Choose a reason for hiding this comment

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

이미 nil Check를 했으니까 Force Unwrapping은 어떨까요?

Suggested change
while node != nil {
guard let currentNode = node else {
return false
}
if visitedNodes.contains(currentNode) {
return true
}
visitedNodes.insert(currentNode)
node = currentNode.next
}
while node != nil {
if visitedNodes.contains(node!) {
return true
}
visitedNodes.insert(node!)
node = node!.next
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

훨씬 깔끔하네요! 감사합니답!
force unwrapping은 지양하려고 하구 있어요 수정하다가 윗 라인이 날아가거나 할 수도 있으니까 만약을 위해서ㅎㅎ


return false
}

// O(n) time / O(1) space
func hasCycleFloyd(_ head: ListNode?) -> Bool {
var slow = head
var fast = head

while fast != nil && fast?.next != nil {
slow = slow?.next
fast = fast?.next?.next

if slow === fast {
return true
}
}

return false
}
}
118 changes: 118 additions & 0 deletions pacific-atlantic-water-flow/sonjh1217.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
class Solution {
// O(m*n) time / O(m*n) space
func pacificAtlanticBFS(_ heights: [[Int]]) -> [[Int]] {
var result = [[Int]]()
guard let first = heights.first else {
return result
}
let m = heights.count
let n = first.count

var goesPacific = Array(repeating: Array(repeating: false, count: n), count: m)
var goesAtlantic = Array(repeating: Array(repeating: false, count: n), count: m)
let directions = [(1,0), (-1,0), (0,1), (0,-1)]

func bfs(queue: [(Int, Int)], goes: inout [[Bool]]) {
var queue = queue
var head = 0
for (i, j) in queue {
goes[i][j] = true
}

while head < queue.count {
var (i, j) = queue[head]
head += 1

for (di, dj) in directions {
let ni = i + di
let nj = j + dj
if ni >= 0
&& ni < m
&& nj >= 0
&& nj < n
&& !goes[ni][nj]
&& heights[ni][nj] >= heights[i][j] {
goes[ni][nj] = true
queue.append((ni, nj))
}
}
}
}
Copy link
Contributor

@yhkee0404 yhkee0404 Sep 20, 2025

Choose a reason for hiding this comment

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

재밌는 거 하나 공유하고 갑니다! (저만 재밌음 주의)
최단거리 구하지는 못하지만 Flood-Fill 하기는 좋아요!

Suggested change
func bfs(queue: [(Int, Int)], goes: inout [[Bool]]) {
var queue = queue
var head = 0
for (i, j) in queue {
goes[i][j] = true
}
while head < queue.count {
var (i, j) = queue[head]
head += 1
for (di, dj) in directions {
let ni = i + di
let nj = j + dj
if ni >= 0
&& ni < m
&& nj >= 0
&& nj < n
&& !goes[ni][nj]
&& heights[ni][nj] >= heights[i][j] {
goes[ni][nj] = true
queue.append((ni, nj))
}
}
}
}
func depthFirstBreadthSecondSearch(queue: [(Int, Int)], goes: inout [[Bool]]) {
var stack = queue
for (i, j) in stack {
goes[i][j] = true
}
while !stack.isEmpty {
let (i, j) = stack.removeLast()
for (di, dj) in directions {
let ni = i + di
let nj = j + dj
if ni >= 0
&& ni < m
&& nj >= 0
&& nj < n
&& !goes[ni][nj]
&& heights[ni][nj] >= heights[i][j] {
goes[ni][nj] = true
stack.append((ni, nj))
}
}
}
}

Copy link
Contributor Author

@sonjh1217 sonjh1217 Sep 20, 2025

Choose a reason for hiding this comment

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

음.. 저도 removeLast도 시도해보긴 했었는데.. 이점을 찾기가 어렵더라구요ㅠ 어떤 점이 좋은가요?

Copy link
Contributor

@yhkee0404 yhkee0404 Sep 20, 2025

Choose a reason for hiding this comment

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

구현하신 dfs의 재귀함수 대신 stack 반복문으로 구현하실 때 이 구현과 비교해 보시면 DFS도 BFS도 아니면서 일부 중복 검사도 head도 생략 가능한 혼종임을 아실 수 있으실 거예요. 다만 익숙하지 않으면 혼동을 초래할지도 몰라서 주의해야 하지만 오히려 DFS와 BFS 구현 실수를 줄이는 데 기여하는 변별력을 높일 수 있는 방법이라고도 생각해요 ㅎㅎ

Copy link
Contributor Author

Choose a reason for hiding this comment

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

아.. 구현의 이점을 말씀하신 거군요! 공감합니당ㅎㅎ


var pacificStarts = [(Int, Int)]()
var atlanticStarts = [(Int, Int)]()
for i in 0..<m {
pacificStarts.append((i, 0))
atlanticStarts.append((i, n-1))
}

for j in 0..<n {
pacificStarts.append((0, j))
atlanticStarts.append((m-1, j))
}

bfs(queue: pacificStarts, goes: &goesPacific)
bfs(queue: atlanticStarts, goes: &goesAtlantic)

for i in 0..<m {
for j in 0..<n {
if goesPacific[i][j] && goesAtlantic[i][j] {
result.append([i, j])
}
}
}
return result
}

// O(m*n) time / O(m*n) space
func pacificAtlanticDFS(_ heights: [[Int]]) -> [[Int]] {
var result = [[Int]]()
guard let first = heights.first else {
return result
}
let m = heights.count
let n = first.count

var goesPacific = Array(repeating: Array(repeating: false, count: n), count: m)
var goesAtlantic = Array(repeating: Array(repeating: false, count: n), count: m)
let directions = [(1,0), (-1,0), (0,1), (0,-1)]

func dfs(i: Int, j: Int, goes: inout [[Bool]]) {
if goes[i][j] {
return
}
goes[i][j] = true

for (di, dj) in directions {
let ni = i + di
let nj = j + dj
if ni >= 0
&& ni < m
&& nj >= 0
&& nj < n
&& heights[ni][nj] >= heights[i][j] {
dfs(i: ni, j: nj, goes: &goes)
}
}
}

for i in 0..<m {
dfs(i: i, j: 0, goes: &goesPacific)
dfs(i: i, j: n-1, goes: &goesAtlantic)
}

for j in 0..<n {
dfs(i: 0, j: j, goes: &goesPacific )
dfs(i: m-1, j: j, goes: &goesAtlantic )
}

for i in 0..<m {
for j in 0..<n {
if goesPacific[i][j] && goesAtlantic[i][j] {
result.append([i, j])
}
}
}
return result
}
}