Create 102. Binary Tree Level Order Traversal.md#7
Conversation
hayashi-ay
left a comment
There was a problem hiding this comment.
良いのではないでしょうか。BFSでもdequeでなくてlistを使ってみたり、DFSで書いてみても良いかもですね。
There was a problem hiding this comment.
resultはもう少し命名頑張っても良いかも。level_ordered_valuesとかどうでしょうか?
There was a problem hiding this comment.
ありがとうございます。level_ordered_values良いですね、参考にします。
There was a problem hiding this comment.
こうも書けますね。
| next_level_nodes = deque() | |
| next_level_nodes.append(root) | |
| next_level_nodes = deque([root]) |
There was a problem hiding this comment.
ドキュメントに軽く目を通して置くと良いと思います。
Returns a new deque object initialized left-to-right (using append()) with data from iterable. If iterable is not specified, the new deque is empty.
https://docs.python.org/3/library/collections.html#deque-objects
There was a problem hiding this comment.
popleft() すると n = len(next_level_nodes) として、時間計算量 O(n) かかってしまいます。理由は、 popleft() した場合、右側の要素を全て 1 つずつ左にずらさなければならないためです。 (CPython の実装がそのようになっているかは確認しておりません。念のため確認をお願いいたします。)
node の list を 2 つ持ち、片方を for 文で回し、もう片方に子ノードを入れていき、 1 レベル終わったら後者を全車に代入する、という実装はいかがでしょうか?
There was a problem hiding this comment.
dequeなのでpopleftの計算量はO(1)ではないですか?
https://docs.python.org/3/library/collections.html#collections.deque
Deques are a generalization of stacks and queues (the name is pronounced “deck” and is short for “double-ended queue”). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.
There was a problem hiding this comment.
nodchipさん、ahayashiさん
ありがとうございます。listを使って、popleftなしでも書き直してみます。
実装を確認してみました。
https://github.com/python/cpython/blob/main/Modules/_collectionsmodule.c
static PyObject *
deque_popleft_impl(dequeobject *deque)
/*[clinic end generated code: output=62b154897097ff68 input=1571ce88fe3053de]*/
{
PyObject *item;
block *prevblock;
if (Py_SIZE(deque) == 0) {
PyErr_SetString(PyExc_IndexError, "pop from an empty deque");
return NULL;
}
assert(deque->leftblock != NULL);
item = deque->leftblock->data[deque->leftindex];
deque->leftindex++;
Py_SET_SIZE(deque, Py_SIZE(deque) - 1);
deque->state++;
if (deque->leftindex == BLOCKLEN) {
if (Py_SIZE(deque)) {
assert(deque->leftblock != deque->rightblock);
prevblock = deque->leftblock->rightlink;
freeblock(deque, deque->leftblock);
CHECK_NOT_END(prevblock);
MARK_END(prevblock->leftlink);
deque->leftblock = prevblock;
deque->leftindex = 0;
} else {
assert(deque->leftblock == deque->rightblock);
assert(deque->leftindex == deque->rightindex+1);
/* re-center instead of freeing a block */
deque->leftindex = CENTER + 1;
deque->rightindex = CENTER;
}
}サイズやindexのインクリメントで、O(1)と思います。もし、参照先や読み方間違っていたらぜひ教えて欲しいです。
There was a problem hiding this comment.
申し訳ありません。 list で popleft() をしているのだと勘違いしました。失礼いたしました。
There was a problem hiding this comment.
いえ、アドバイスと確認の機会、ありがとうございました。
参考になりました。
listによる解法を追加
There was a problem hiding this comment.
same_level: 同じ階層(level)と判断されたノードの値
current_level: 現在注目している(各子ノードを調べている)ノードたち
で書いていました。
There was a problem hiding this comment.
current_levelで統一して良さそうな気がします。
あるいは、level_ordered_values.append([])して、level_ordered_values[-1]に直接入れていくこともできますね。
There was a problem hiding this comment.
たしかに、分けて変数名つけるほどのメリットは感じず、nodeとvalueで分かれていれば十分ですね。
下記はたしかにおっしゃる通りですね、覚えておきます。ありがとうございます。
level_ordered_values.append([])して、level_ordered_values[-1]に直接入れていくこともできますね。
There was a problem hiding this comment.
私はそもそもローカル変数に current を付けておけばいい名前になっているというのが相当違和感です。current は多くの場合、context のようなグローバルな設定などに用いられる傾向が強く、今注目しているもの、というつもりだと標準的用法からかなりずれを感じます。変数名は長ければ読みやすい訳ではないんです。previous, next との対比ならばまだしも。
There was a problem hiding this comment.
確かにここでもlevel_nodes, next_level_nodesで十分通じそうですね。
There was a problem hiding this comment.
odaさん、liquo-riceさん
ありがとうございます。currentは良かれと思って使っていたので、考えを修正します。
また、参考のリンクもありがとうございます。
https://source.chromium.org/search?q="current"%20-concurrent%20filepath:.*%5C.cc$
|
list の時は pop(0) ですね。 by Odaさん |
https://leetcode.com/problems/binary-tree-level-order-traversal/description/