-
Notifications
You must be signed in to change notification settings - Fork 0
Solve 78_subsets_medium #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
78_subsets_medium/README.md
Outdated
| - `_ith_binary_digit`関数を定義して、整数をビットマスクとして解釈する際に、`i`番目のビットが立っているかどうかを判定する処理を分離した。 | ||
|
|
||
| # 別解1. backtracking | ||
| - backtrackingを用いて部分集合を生成する方法。再帰的に要素を選択するかどうかを決定し、部分集合を構築していく。`subset`変数は参照渡しで更新され、最後に`all_subsets`に追加するときにコピーされる。そのため、更新の順序に注意が必要。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.python.org/ja/3.7/faq/programming.html#id18
言いたいことはわかりますが、Pythonに参照渡しはないです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。「参照渡し」という言葉をもっぱら「ポインタ渡し(参照の値渡し)」のことかと思っておりました。
そして「参照の参照渡し」(�Python公式ドキュメントの参照渡し)はPythonでは実装されていないのですね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
こちらもかなり参考になると感じました。
【Python】Python に参照渡しは存在しない話|CREFIL
- 値渡し
- 呼び出し先で再代入した場合
- 呼び出し元に影響なし
- 呼び出し先でオブジェクトの操作をした場合
- 呼び出し元に影響なし
- 呼び出し先で再代入した場合
- 参照渡し
- 呼び出し先で再代入した場合
- 呼び出し元変数の参照先も変わる
- 呼び出し先でオブジェクトの操作をした場合
- 呼び出し元変数が参照しているオブジェクトも変わる
- 呼び出し先で再代入した場合
- 参照の値渡し
- 呼び出し先で再代入した場合
- 呼び出し元変数の参照先は変わらず、影響を受けなくなる
- 呼び出し先でオブジェクトの操作をした場合
- 呼び出し元変数が参照しているオブジェクトも変わる
- 呼び出し先で再代入した場合
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
代入のたびにメモリの番地が変わる仕様であるというのも知りませんでした。
なお、小さい値( 1,2,3など)は、よく使われるからためプリロードされているようです。(https://medium.com/techtofreedom/10-python-interview-questions-for-senior-developers-4fefe773719a)
# Pythonでは代入のたびにメモリの場所が変わる
# 代入は値の評価、値のメモリ確保→変数へのバインドがなされるらしい
x = 100000
print(id(x)) # 4566145616
x = 100000
print(id(x)) # 4566148464
x = 100000
print(id(x)) # 4566148784
# 小さい値のプリロード
x = 1
print(id(x)) # 4393378672
x = 1
print(id(x)) # 4393378672
| # 別解2. 再帰的な方法 | ||
| - (backtrackingとは異なる方法で)再帰的に部分集合を生成する方法。 | ||
| - `subsets(nums: list[int])`関数を用いて再帰を回す | ||
| - `subsets(nums[1:])`に`nums[0]`を含める場合と含めない場合の2通りを考えて、全ての部分集合を生成する。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
スライスを使うとコピーが発生し、O(n)かかるので、indexで範囲指定をしたほうが良いかもしれません。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確かにおっしゃる通りですね、ご指摘ありがとうございます。
| - `subsets(nums[1:])`に`nums[0]`を含める場合と含めない場合の2通りを考えて、全ての部分集合を生成する。 | ||
| - 時間計算量:`O(n * 2^n)` | ||
| - 空間計算量:`O(n * 2^n)` | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
特に問題ないです。このあたりからいくつか別解を見てもいいかもしれません。
https://github.com/olsen-blue/Arai60/pull/52/files
…k and extend methods
問題へのリンク
Subsets - LeetCode
言語
Python
問題の概要
与えられた整数のリストから、すべての部分集合を生成する問題。
自分の解法 bit演算を用いて解く
全ての部分集合は、
numsの要素数をnとしたとき、2^n通り存在する。各部分集合は、0から2^n - 1までの整数をビットマスクとして解釈することで生成できる。O(n * 2^n)O(n * 2^n)step2
_ith_binary_digit関数を定義して、整数をビットマスクとして解釈する際に、i番目のビットが立っているかどうかを判定する処理を分離した。別解1. backtracking
backtrackingを用いて部分集合を生成する方法。再帰的に要素を選択するかどうかを決定し、部分集合を構築していく。
subset変数は参照渡しで更新され、最後にall_subsetsに追加するときにコピーされる。そのため、更新の順序に注意が必要。backtrackingはコードが簡潔だが、可読性が低くなることがあると感じた
時間計算量:
O(n * 2^n)空間計算量:
O(n * 2^n)こちらの動画を参考にした。
別解2. 再帰的な方法
subsets(nums: list[int])関数を用いて再帰を回すsubsets(nums[1:])にnums[0]を含める場合と含めない場合の2通りを考えて、全ての部分集合を生成する。O(n * 2^n)O(n * 2^n)次に解く問題の予告