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
35 changes: 35 additions & 0 deletions pullrequests/symmetric_tree/step1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//lint:file-ignore U1000 Ignore all unused code
package symmetrictree

type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}

/*
レビュワーの方へ:
- このコードは既にGoの標準のフォーマッタで整形済みです。演算子の周りにスペースがあったりなかったりしますが、これはGoのフォーマッタによるもので、優先順位の高い演算子の周りにはスペースが入らず、低い演算子の周りには入るようになっています。https://qiita.com/tchssk/items/77030b4271cd192d0347
*/

/*
初見で解くことができなかったので、他の解法を見て解いた。再帰の練習が足りてなさそう。
Copy link

Choose a reason for hiding this comment

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

再帰は仕事の分担でよく説明していて一定の成果が出ているように見えていますが、混乱している気持ちはあんまり分かっていません。なんか余計なことを考えているようには見えます。

Copy link
Owner Author

Choose a reason for hiding this comment

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

再帰自体は混乱せずに理解はできていてコードは読めばすぐに理解できたのですが、この問題の解法(どのようにしてsymmetricかを判断するか)自体が思いつかなかった感じです

*/
func isSymmetricRecursive(root *TreeNode) bool {
// 問題的にはrootはnilにならないのでこの処理は必要ないが
// 一応nilのときはtrue扱いにすると決めて書いた
if root == nil {
return true
}
return isMirror(root.Left, root.Right)
Comment on lines +21 to +24

Choose a reason for hiding this comment

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

個人的にも nil のときには true が自然だと思います。その場合、以下のようにすると最初の分岐が不要になりそうです。

Suggested change
if root == nil {
return true
}
return isMirror(root.Left, root.Right)
return isMirror(root, root)

Copy link
Owner Author

Choose a reason for hiding this comment

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

確かにそうですね。ありがとうございます

}

func isMirror(left, right *TreeNode) bool {
if left == nil && right == nil {
return true
}
if left == nil || right == nil {
return false
}
return left.Val == right.Val && isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left)

Choose a reason for hiding this comment

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

少し1行が長くなっていて、かつ「現在着目しているノードの話」と「子ノードの話」が含まれた条件になっているので、個人的には分割したほうがスッキリする気がします。

Suggested change
return left.Val == right.Val && isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left)
if left.Val != right.Val {
return false
}
return isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left)

}
36 changes: 36 additions & 0 deletions pullrequests/symmetric_tree/step2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//lint:file-ignore U1000 Ignore all unused code
package symmetrictree

import "container/list"

/*
レビュワーの方へ:
- このコードは既にGoの標準のフォーマッタで整形済みです。演算子の周りにスペースがあったりなかったりしますが、これはGoのフォーマッタによるもので、優先順位の高い演算子の周りにはスペースが入らず、低い演算子の周りには入るようになっています。https://qiita.com/tchssk/items/77030b4271cd192d0347
*/

/*
イテレーティブにも解いてみた。BFSなのでキューを使って実装した。
*/
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
queue := list.New()
queue.PushBack(root.Left)
queue.PushBack(root.Right)
Comment on lines +19 to +20
Copy link

Choose a reason for hiding this comment

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

私は、この2つずつ入っている、という方法はあまり好みません。
本当に2つずつ入っているのか、コード全体を見ないと分かりません。
コンパイル時の型チェックが効きません。

少々面倒でも struct 作ったほうがいいんじゃないでしょうか。

Choose a reason for hiding this comment

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

同意見です。型レベルでペアであることが保証されているとバグが起きにくそうです。

for queue.Len() > 0 {
left := queue.Remove(queue.Front()).(*TreeNode)
right := queue.Remove(queue.Front()).(*TreeNode)
if left == nil && right == nil {
continue
}
if left == nil || right == nil || left.Val != right.Val {
return false
}
queue.PushBack(left.Left)
queue.PushBack(right.Right)
queue.PushBack(left.Right)
queue.PushBack(right.Left)
}
return true
}