Conversation
| if complement in num_to_index: | ||
| return [i, num_to_index[complement]] | ||
| num_to_index[num] = i | ||
| raise ValueError("nums is invalid. Can't return 2 indices.") |
There was a problem hiding this comment.
nums is invalidという文言からは空配列や要素の型が非想定のような状況を連想するので、単に条件を満たす要素組を見つけられなかったことを伝えたいのならCannot find a pair of elements that adds up to target value.やThere is no pair whose sum equals to target value.のほうが適切だと思います。
There was a problem hiding this comment.
ありがとうございます。
空配列や要素の型が非想定のような状況 のほかに組み合わせが見つからなかった場合も含めて nums is invalid というように返していたのですが、改めて考えてみて同意です。
そもそも入力に型ヒントが与えられていて numsが List[int] 以外になる可能性は一旦考えなくてもいいのと、一連の処理の後に来るエラーなのでもっと具体的な内容でもいいと思い直したためです。step 4として追記しました。
| ### 解法2: 二重ループ | ||
|
|
||
| - 選択肢を増やしたいので二重ループでも解けるようにする。 | ||
| - Space Complexity を1にするとしたらこうするのがいいが、Time Complexity が非効率なので実践的ではないかも。 |
There was a problem hiding this comment.
入力の配列長と許容されうる時間制限を与えられたとしてこの解法がそれに収まるかを概算できるといいかもしれません。
There was a problem hiding this comment.
ありがとうございます!
Python を約 10^6~10^7 ステップ/秒と仮定した場合に、
Yuto729/leetcode#16 (comment)
今回は、
- 入力の配列長: 最大10^4
- 許容されうる時間制限: 2 sec
- 解法2の最悪時間計算量: O(N^2) (二重ループで約 10^8 / 2 = 5 × 10^7 ステップ)
なので、解法2を使うとなると、所要時間は最悪5 sec ほどになるのでやめておいた方がいいと言えますね。
| - 最初に思いついた流れ通りに実装した | ||
| - diff_to_index という名前はちょっと詰め込みすぎ感があるかも。厳密にいうと、diff_between_target_and_num_to_index なんだけれども長ったらしくなってしまうので略して diff_to_index とした。 | ||
| - Time Complexity: O(n), Space Complexity: O(n) | ||
| - もう1個くらい解法を出したかったが、パッと思いつかなかったので step 2 に進む |
There was a problem hiding this comment.
ありがとうございます。
確かに全探索でも許容されうる時間内に収まりそうなら、解法たりえますね。
無意識のうちに外していました。以降全探索も考慮してみます!
| def twoSum(self, nums: List[int], target: int) -> List[int]: | ||
| num_to_index = {} | ||
| for index, num in enumerate(nums): | ||
| complement = target - num |
There was a problem hiding this comment.
セイウチ演算子というものを使っても書けそうです
https://peps.python.org/pep-0572/
There was a problem hiding this comment.
ご教示いただき、ありがとうございます。
こう書けるのですね。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
num_to_index = {}
for index, num in enumerate(nums):
if not (complement := target - num) in num_to_index:
num_to_index[num] = index
continue
return [ index, num_to_index[complement] ]
raise ValueError("Can't find the pair of elements whose total is the target value.")個人的には、1行減るメリットこそあれど可読性が落ちるので、あえてこの解法では使わないかなとは思います。
ちなみに Go で同じように書くと complement が undefined になってしまいます。lexical scope の言語差をより意識しないといけなくなる感じがあるので、個人的にはあまり進んで使わないかなという所感です。
func twoSum(nums []int, target int) []int {
numToIndex := make(map[int]int)
for index, num := range nums {
if complement := target - num; !contains(numToIndex, complement) {
numToIndex[num] = index
continue
}
// ERROR: undefined: complement
return []int{index, numToIndex[complement]}
}
panic("Can't find the pair of elements whose total is the target value.")
}| def twoSum(self, nums: List[int], target: int) -> List[int]: | ||
| num_to_index = {} | ||
| for index, num in enumerate(nums): | ||
| if not (complement := target - num) in num_to_index: |
There was a problem hiding this comment.
not ... in より not in のほうをよく見かけます。 PEP8 には not ... is と is not の場合は書かれているようです。
if (complement := target - num) not in num_to_index:https://peps.python.org/pep-0008/#programming-recommendations
Use is not operator rather than not ... is.
There was a problem hiding this comment.
ありがとうございます。
今まで自分は、not ... is と is not の場合は後者を取っていたのですが、not ... in と not in の場合は前者をとってしまっていたことに気づけました。not inの方が何を否定しているのかがわかりやすい感じがありますね。
以降は一貫性向上のため、not ... in と not in の時も後者を取るようにしようと思います。
https://leetcode.com/problems/two-sum/description/
Next: https://leetcode.com/problems/group-anagrams/description/