Skip to content

Create 102. Binary Tree Level Order Traversal.md#7

Merged
Mike0121 merged 2 commits intomainfrom
102.-Binary-Tree-Level-Order-Traversal
Nov 1, 2025
Merged

Create 102. Binary Tree Level Order Traversal.md#7
Mike0121 merged 2 commits intomainfrom
102.-Binary-Tree-Level-Order-Traversal

Conversation

@Mike0121
Copy link
Copy Markdown
Owner

@Mike0121 Mike0121 commented May 2, 2024

Copy link
Copy Markdown

@hayashi-ay hayashi-ay left a comment

Choose a reason for hiding this comment

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

良いのではないでしょうか。BFSでもdequeでなくてlistを使ってみたり、DFSで書いてみても良いかもですね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

resultはもう少し命名頑張っても良いかも。level_ordered_valuesとかどうでしょうか?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。level_ordered_values良いですね、参考にします。

Comment on lines 72 to 73
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こうも書けますね。

Suggested change
next_level_nodes = deque()
next_level_nodes.append(root)
next_level_nodes = deque([root])

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

存じ上げなかったです、ありがとうございます。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ドキュメントに軽く目を通して置くと良いと思います。

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

popleft() すると n = len(next_level_nodes) として、時間計算量 O(n) かかってしまいます。理由は、 popleft() した場合、右側の要素を全て 1 つずつ左にずらさなければならないためです。 (CPython の実装がそのようになっているかは確認しておりません。念のため確認をお願いいたします。)

node の list を 2 つ持ち、片方を for 文で回し、もう片方に子ノードを入れていき、 1 レベル終わったら後者を全車に代入する、という実装はいかがでしょうか?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

list を使っていると見間違えました。失礼いたしました。

Copy link
Copy Markdown
Owner Author

@Mike0121 Mike0121 May 2, 2024

Choose a reason for hiding this comment

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

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)と思います。もし、参照先や読み方間違っていたらぜひ教えて欲しいです。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

申し訳ありません。 list で popleft() をしているのだと勘違いしました。失礼いたしました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

いえ、アドバイスと確認の機会、ありがとうございました。
参考になりました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

for node in current_level_nodes:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます、こちらは修正必須ですね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

same_levelとcurrent_levelの違いは何ですか?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

same_level: 同じ階層(level)と判断されたノードの値
current_level: 現在注目している(各子ノードを調べている)ノードたち
で書いていました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

current_levelで統一して良さそうな気がします。
あるいは、level_ordered_values.append([])して、level_ordered_values[-1]に直接入れていくこともできますね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

たしかに、分けて変数名つけるほどのメリットは感じず、nodeとvalueで分かれていれば十分ですね。
下記はたしかにおっしゃる通りですね、覚えておきます。ありがとうございます。

level_ordered_values.append([])して、level_ordered_values[-1]に直接入れていくこともできますね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私はそもそもローカル変数に current を付けておけばいい名前になっているというのが相当違和感です。current は多くの場合、context のようなグローバルな設定などに用いられる傾向が強く、今注目しているもの、というつもりだと標準的用法からかなりずれを感じます。変数名は長ければ読みやすい訳ではないんです。previous, next との対比ならばまだしも。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

確かにここでもlevel_nodes, next_level_nodesで十分通じそうですね。

Copy link
Copy Markdown
Owner Author

@Mike0121 Mike0121 May 3, 2024

Choose a reason for hiding this comment

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

odaさん、liquo-riceさん
ありがとうございます。currentは良かれと思って使っていたので、考えを修正します。
また、参考のリンクもありがとうございます。
https://source.chromium.org/search?q="current"%20-concurrent%20filepath:.*%5C.cc$

@Mike0121
Copy link
Copy Markdown
Owner Author

Mike0121 commented May 2, 2024

list の時は pop(0) ですね。
https://docs.python.org/3/tutorial/datastructures.html

by Odaさん

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants