Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Solution {
// Time O(N)
Copy link
Contributor

Choose a reason for hiding this comment

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

알고달레 풀이 1index처럼 for 반복문이 시간 병목이 됩니다. 선형 시간으로 줄일 수는 있던데 좀 어렵더라고요!

Suggested change
// Time O(N)
// Time O(N^2)

// Space O(N)
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
if preorder.isEmpty {
return nil
}

let totalCount = preorder.count
let rootNode = TreeNode(preorder[0])
var rootIndex = 0

for (index, value) in inorder.enumerated() {
if value == rootNode.val {
rootIndex = index
break
}
}

rootNode.left = buildTree(Array(preorder[1..<rootIndex + 1]), Array(inorder[0..<rootIndex + 1]))
Copy link
Contributor

Choose a reason for hiding this comment

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

preorder.countinorder.count가 같음을 보장하려면 이렇게 줄일 수 있어요:

Suggested change
rootNode.left = buildTree(Array(preorder[1..<rootIndex + 1]), Array(inorder[0..<rootIndex + 1]))
rootNode.left = buildTree(Array(preorder[1..<rootIndex + 1]), Array(inorder[0..<rootIndex]))

rootNode.right = buildTree(Array(preorder[1 + rootIndex..<totalCount]), Array(inorder[1 + rootIndex..<totalCount]))
Copy link
Contributor

Choose a reason for hiding this comment

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

마찬가지로 알고달레 풀이 1에서처럼 Slice가 시간과 공간 병목이 될 수 있어요. 그래서 Slice 대신 Two Pointers를 사용하거나 또는 Swift에서는 다음과 같이 Array 형변환을 피하도록 고치면 선형 공간으로는 최적화할 수 있습니다:

Suggested change
// Space O(N)
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
if preorder.isEmpty {
return nil
}
let totalCount = preorder.count
let rootNode = TreeNode(preorder[0])
var rootIndex = 0
for (index, value) in inorder.enumerated() {
if value == rootNode.val {
rootIndex = index
break
}
}
rootNode.left = buildTree(Array(preorder[1..<rootIndex + 1]), Array(inorder[0..<rootIndex + 1]))
rootNode.right = buildTree(Array(preorder[1 + rootIndex..<totalCount]), Array(inorder[1 + rootIndex..<totalCount]))
// Space O(N)
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
return buildTree(preorder[...], inorder[...])
}
func buildTree(_ preorder: ArraySlice<Int>, _ inorder: ArraySlice<Int>) -> TreeNode? {
if preorder.isEmpty {
return nil
}
let rootNode = TreeNode(preorder.first!)
var rootIndex = 0
for (index, value) in inorder.enumerated() {
if value == rootNode.val {
rootIndex = index
break
}
}
rootNode.left = buildTree(preorder[preorder.startIndex + 1..<preorder.startIndex + rootIndex + 1], inorder[inorder.startIndex..<inorder.startIndex + rootIndex])
rootNode.right = buildTree(preorder[preorder.startIndex + 1 + rootIndex..<preorder.endIndex], inorder[inorder.startIndex + 1 + rootIndex..<inorder.endIndex])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오! 이건 생각지도 못한 부분이네요 조금 더 최적화할 수 있는 방법을 배워갑니다


return rootNode
}
}

29 changes: 29 additions & 0 deletions subtree-of-another-tree/delight010.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Solution {
// Time O(M * N)
// Space O(N)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Space O(N)
// Space O(M + N)

func isSubtree(_ root: TreeNode?, _ subRoot: TreeNode?) -> Bool {
if let root = root, let subRoot = subRoot {
if root.val == subRoot.val {
return dfs(root.left, subRoot: subRoot.left) && dfs(root.right, subRoot: subRoot.right) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
}
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
}

return false
}

private func dfs(_ root: TreeNode?, subRoot: TreeNode?) -> Bool {
if root == nil && subRoot == nil {
return true
}

if let root = root, let subRoot = subRoot {
if root.val == subRoot.val {
return dfs(root.left, subRoot: subRoot.left) && dfs(root.right, subRoot: subRoot.right)
}
}

return false
Copy link
Contributor

Choose a reason for hiding this comment

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

사소한 간소화입니다 ㅎㅎ

Suggested change
if let root = root, let subRoot = subRoot {
if root.val == subRoot.val {
return dfs(root.left, subRoot: subRoot.left) && dfs(root.right, subRoot: subRoot.right) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
}
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
}
return false
}
private func dfs(_ root: TreeNode?, subRoot: TreeNode?) -> Bool {
if root == nil && subRoot == nil {
return true
}
if let root = root, let subRoot = subRoot {
if root.val == subRoot.val {
return dfs(root.left, subRoot: subRoot.left) && dfs(root.right, subRoot: subRoot.right)
}
}
return false
if let root = root, let subRoot = subRoot {
return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
}
return root == nil && subRoot == nil
}
private func dfs(_ root: TreeNode?, _ subRoot: TreeNode?) -> Bool {
if let root = root, let subRoot = subRoot {
return root.val == subRoot.val && dfs(root.left, subRoot.left) && dfs(root.right, subRoot.right)
}
return root == nil && subRoot == nil

Copy link
Contributor Author

Choose a reason for hiding this comment

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

짧으면서도 이해하기 쉬운 코드 덕분에 공부가 되었습니다.

}
}