-
문제접근
- DFS를 사용하여 p, q를 탐색
- 탐색하며 지나온 TreeNode를 배열로 기록
- p,q를 찾았다면, 각자 지나온 기록 Treenode 배열에서 겹치는 마지막 element탐색
- 탐색 결과 반환
정답코드
성능이 처참하다..
831msBeats5.74%
더보기/** * Definition for a binary tree node. * public class TreeNode { * public var val: Int * public var left: TreeNode? * public var right: TreeNode? * public init(_ val: Int) { * self.val = val * self.left = nil * self.right = nil * } * } */ class Solution { func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? { guard let root = root, let p = p, let q = q else { return nil } var qMap = [TreeNode]() var pMap = [TreeNode]() func dfs(_ root: TreeNode?, _ p: TreeNode, _ q: TreeNode, _ history: [TreeNode]) { guard let root else { return } var newHistory = history newHistory.append(root) if root.val == p.val { pMap = newHistory } if root.val == q.val { qMap = newHistory } dfs(root.left, p, q, newHistory) dfs(root.right, p, q, newHistory) } dfs(root, p, q, []) let common = qMap.lastIndex(where: { q in let result:Bool = pMap.contains(where: { q.val == $0.val}) return result }) if let common { return qMap[common] } else{ return nil } } }
모범코드
1. 32ms가 걸리는, 대중적인 코드
더보기class Solution { func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? { guard let root = root else { return nil } if root === p || root === q { return root } let left = lowestCommonAncestor(root.left, p, q) let right = lowestCommonAncestor(root.right, p, q) if left != nil && right != nil { return root } return left != nil ? left : right } }
2. 상위 0.2%의 13ms 코드
더보기class Solution { func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? { guard let root = root else { return nil } var stack: [(TreeNode, NodeState)] = [(root, .bothPending)] var oneNodeFound = false var lcaIndex = -1 while !stack.isEmpty { var (node, state) = stack.removeLast() if state == .bothPending { // Before traversing children, check if this is one of the target nodes if node === p || node === q { if oneNodeFound { return stack[lcaIndex].0 // LCA is at lcaIndex in stack } oneNodeFound = true lcaIndex = stack.count // Store LCA candidate index } // Push back with updated state and process left child stack.append((node, .leftDone)) if let left = node.left { stack.append((left, .bothPending)) } } else if state == .leftDone { // Process right child stack.append((node, .bothDone)) if let right = node.right { stack.append((right, .bothPending)) } } else { // Node fully processed, check if we need to update LCA index if oneNodeFound && lcaIndex == stack.count { lcaIndex -= 1 // Reduce LCA candidate index } } } return nil // Should never reach here } } enum NodeState { case bothPending case leftDone case bothDone } /* Iterative DFS + parent tracking Time: O(n) Space: O(n) -------------------------------------------------------------------- Step 1: Map every node to it's parent Step 2: Iterate over every node from p, to the root, and add each node to a set Step 3: Iterate over every node from q, to the root, and check the set The first node found that is common between both sets is the LCA */
재학습 코드
모범코드 1을 이해하고 내가 작성한 코드 -> 24ms
코드흐름:
- let left, let right에서 dfs가 진행
- 최하단 노드까지 진행, 최하단 노드의 left, right는 존재하지 않으므로, left, right가 nil
- 둘 다 nil이므로, if 구문의 조건을 만족하는 경우가 없어서 nil 반환
- 이를 반복하다 p or q와 동일한 instance가 탐색됨, 해당 instance( root ) 반환
- left or right에 반환된 값이 하나만 존재하면 상위 노드로 해당 값 반환
- 반복되다가, left, right가 둘 다 존재하는 경우 발생, left, right 둘 다 존재하면 해당 노드가 LCA, 그러므로 root를 반환
- 6 경우가 발생했다면, 6경우의 상위 노드의 left or right에 LCA가 반환 될 것, 그 때, 다른 한 쪽에서는 nil이 반환됨
- 그러면 left or right가 반복 반환되며 정답을 반환
더보기class Solution { func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? { guard let root else { return nil } if root === q || root === p { return root } let left = lowestCommonAncestor(root.left, p, q) let right = lowestCommonAncestor(root.right, p, q) if left != nil && right != nil { return root } if let left { return left } if let right { return right } return nil } }
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
matrix_Leetcode_54. Spiral Matrix (0) 2025.04.14 matrix_Leetcode_240. Search a 2D Matrix II (0) 2025.04.10 BinaryTree,BFS_Leetcode_199. Binary Tree Right Side View (0) 2025.04.03 PrefixSum_Leetcode_2389. Longest Subsequence With Limited Sum [swift] (0) 2025.04.01 BinaryTree_Leetcode_114. Flatten Binary Tree to Linked List [swift] (0) 2025.04.01