Skip to content

Commit 76410da

Browse files
committed
Refine Rc<RefCell<...>> explanation and remove redundant code in same_tree_rust.md
1 parent 8c618a1 commit 76410da

1 file changed

Lines changed: 2 additions & 51 deletions

File tree

Algorithm/Other/leetcode/100. Same Tree/claude sonnet 4.6 extended/Same_Tree_Rust.md

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -210,67 +210,18 @@ impl Solution {
210210
211211
### 所有権・借用・ライフタイムの活用
212212
213-
`Rc<RefCell<TreeNode>>` という型は、Rustの所有権ルール(「値の所有者は常に1人」)では木構造のような「複数の場所から参照されるデータ」を表現できないため使われています。`Rc` が「複数の共有所有者」を実現し、`RefCell` が「実行時の借用チェック」を提供します。`borrow()` で取り出した `Ref<p_node>` は `p_ref` という変数に束縛されており、この変数のスコープを超えて生きることはありません。これによりダングリングポインタが原理的に発生しません。
213+
`Rc<RefCell<TreeNode>>` という型は、Rustの所有権ルール(「値の所有者は常に1人」)では木構造のような「複数の場所から参照されるデータ」を表現できないため使われています。`Rc` が「複数の共有所有者」を実現し、`RefCell` が「実行時の借用チェック」を提供します。`Rc<RefCell<TreeNode>>::borrow()` で取り出した `Ref<TreeNode>` は `p_ref` などの変数に束縛されており、この変数のスコープを超えて生きることはありません。これによりダングリングポインタが原理的に発生しません。
214214
215215
### ゼロコスト抽象化
216216
217217
`match` による網羅的なパターンマッチは、コンパイル後は単純な分岐命令に変換されます。`Option` の `Some`/`None` もランタイムのオーバーヘッドはなく、ポインタの null チェックと同等のコードが生成されます。
218218
219219
### エラーハンドリング設計
220220
221-
本問題の戻り値は `bool` で十分なため `Result` は使用していません。`borrow()` がパニックする可能性は「既に `borrow_mut()` で可変借用中の場合」のみですが、本実装では `borrow_mut()` を一切呼ばないため実行時パニックは発生しません。`.expect()` などの明示的なパニック制御も不要です
221+
本問題の戻り値は `bool` で十分なため `Result` は使用していません。`Rc<RefCell<...>>` に対して `borrow()` を呼ぶと、もし外部で同時に `borrow_mut()` を使って可変借用されていれば実行時パニックする可能性があります。しかし、本実装では `borrow_mut()` を一切呼ばず、シングルスレッド環境での参照のみを行うため、通常はパニックしません。そのため `.expect()` などの明示的なパニック制御も不要としています
222222
223223
> 📖 **最終用語まとめ**
224224
>
225225
> - **`Ref<T>`**:`RefCell::borrow()` が返す型。スコープを抜けると自動的に借用が解放される
226226
> - **網羅性チェック**:`match` で全パターンを列挙しないとコンパイルエラーになるRustの仕組み。バグの原因となるケース漏れを防ぐ
227227
> - **参照カウント**:`Rc<T>` が内部で持つカウンター。`clone()` で +1、変数がドロップされると -1。0になったらメモリ解放
228-
229-
```rust
230-
use std::rc::Rc;
231-
use std::cell::RefCell;
232-
233-
impl Solution {
234-
pub fn is_same_tree(
235-
p: Option<Rc<RefCell<TreeNode>>>,
236-
q: Option<Rc<RefCell<TreeNode>>>,
237-
) -> bool {
238-
match (p, q) {
239-
// ① 両方 None → 葉の先端に到達。構造が同じなので true
240-
(None, None) => true,
241-
242-
// ② 片方だけ Some → 構造が違う → false
243-
// `|` で「どちらのパターンでも同じ処理」をまとめて表現
244-
(Some(_), None) | (None, Some(_)) => false,
245-
246-
// ③ 両方 Some → 値を取り出して比較し、再帰で子木を確認
247-
(Some(p_node), Some(q_node)) => {
248-
// .borrow() で RefCell の中身への共有参照を取り出す。
249-
// 実行時借用チェックが走るが、borrow_mut() を使わない
250-
// 本実装ではパニックは発生しない。
251-
let p_ref = p_node.borrow();
252-
let q_ref = q_node.borrow();
253-
254-
// 値が違えば即 false(以降の再帰を省略できる)
255-
if p_ref.val != q_ref.val {
256-
return false;
257-
}
258-
259-
// 左の子木を再帰比較。
260-
// clone() は Rc の参照カウントを +1 するだけで O(1)。
261-
// ディープコピー(全ノード複製)は発生しない。
262-
let left_same =
263-
Self::is_same_tree(p_ref.left.clone(), q_ref.left.clone());
264-
265-
// 左が不一致なら右を見るまでもなく false
266-
if !left_same {
267-
return false;
268-
}
269-
270-
// 右の子木を再帰比較し、その結果をそのまま返す
271-
Self::is_same_tree(p_ref.right.clone(), q_ref.right.clone())
272-
}
273-
}
274-
}
275-
}
276-
```

0 commit comments

Comments
 (0)