-
Notifications
You must be signed in to change notification settings - Fork 0
209. Minimum Size Subarray Sum #49
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,154 @@ | ||||||||||||||||||||||||||
| # 209. Minimum Size Subarray Sum | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## 1st | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ### ① | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 右端をループで回しながら、subarray_sum < target となるまで左端を進める、を繰り返す。 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 所要時間: 8:15 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| n: len(nums) | ||||||||||||||||||||||||||
| - 時間計算量: O(n) | ||||||||||||||||||||||||||
| - 空間計算量: O(n) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| assert target > 0 | ||||||||||||||||||||||||||
| left = -1 # exclusive | ||||||||||||||||||||||||||
| subarray_sum = 0 | ||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| for right in range(len(nums)): | ||||||||||||||||||||||||||
| subarray_sum += nums[right] | ||||||||||||||||||||||||||
| while subarray_sum >= target: | ||||||||||||||||||||||||||
| min_length = min(min_length, right - left) | ||||||||||||||||||||||||||
| left += 1 | ||||||||||||||||||||||||||
| subarray_sum -= nums[left] | ||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ### ② | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 左端をループで回すパターン。 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 所要時間: 16:45 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| n: len(nums) | ||||||||||||||||||||||||||
| - 時間計算量: O(n) | ||||||||||||||||||||||||||
| - 空間計算量: O(n) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| subarray_sum = 0 | ||||||||||||||||||||||||||
| end = 0 | ||||||||||||||||||||||||||
| for begin in range(len(nums)): | ||||||||||||||||||||||||||
| while end < len(nums) and subarray_sum < target: | ||||||||||||||||||||||||||
| subarray_sum += nums[end] | ||||||||||||||||||||||||||
| end += 1 | ||||||||||||||||||||||||||
| if subarray_sum >= target: | ||||||||||||||||||||||||||
| min_length = min(min_length, end - begin) | ||||||||||||||||||||||||||
| subarray_sum -= nums[begin] | ||||||||||||||||||||||||||
|
Comment on lines
+53
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
if subarray_sum < target:
break
min_length = min(min_length, end - begin)
subarray_sum -= nums[begin]ただ、begin のループを抜けようとしたらもうひと手間いると思うので、少し流れが違うだけですね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. たしかにそう書けますね。ありがとうございます! |
||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## 2nd | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ### 参考 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - https://discord.com/channels/1084280443945353267/1233603535862628432/1264033965724012656 | ||||||||||||||||||||||||||
| - https://github.com/goto-untrapped/Arai60/pull/40 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 累積和を使ってもよい。 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| assert target > 0 | ||||||||||||||||||||||||||
| cumsum = [0] | ||||||||||||||||||||||||||
| for num in nums: | ||||||||||||||||||||||||||
| cumsum.append(cumsum[-1] + num) | ||||||||||||||||||||||||||
| begin = 0 | ||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| for end in range(len(cumsum)): | ||||||||||||||||||||||||||
| while cumsum[end] - cumsum[begin] >= target: | ||||||||||||||||||||||||||
| min_length = min(min_length, end - begin) | ||||||||||||||||||||||||||
| begin += 1 | ||||||||||||||||||||||||||
|
Comment on lines
+79
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 個人的に二重ループになっていると少し複雑かなと思いました。if 文を使って
Suggested change
|
||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - https://discord.com/channels/1084280443945353267/1225849404037009609/1253024249040474258 | ||||||||||||||||||||||||||
| - https://github.com/SuperHotDogCat/coding-interview/pull/31 | ||||||||||||||||||||||||||
| - https://discord.com/channels/1084280443945353267/1196472827457589338/1246777474927562752 | ||||||||||||||||||||||||||
| - https://github.com/Mike0121/LeetCode/pull/22 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 累積和と二分探索。 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| cumsum = [0] | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. リストなので、 |
||||||||||||||||||||||||||
| for num in nums: | ||||||||||||||||||||||||||
| cumsum.append(cumsum[-1] + num) | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 累積和を求めるときのこの書き方良いですね、参考にします。 |
||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| for i in range(len(cumsum)): | ||||||||||||||||||||||||||
| j = bisect_left(cumsum, cumsum[i] + target) | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i, j はもう少し変数名こだわっても良いかと思いました。 |
||||||||||||||||||||||||||
| if j < len(cumsum): | ||||||||||||||||||||||||||
| min_length = min(min_length, j - i) | ||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - https://discord.com/channels/1084280443945353267/1201211204547383386/1228603635693387808 | ||||||||||||||||||||||||||
| - https://github.com/shining-ai/leetcode/pull/49 | ||||||||||||||||||||||||||
| - https://discord.com/channels/1084280443945353267/1200089668901937312/1219219869510140005 | ||||||||||||||||||||||||||
| - https://github.com/hayashi-ay/leetcode/pull/51 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 全探索。TLE。 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| for begin in range(len(nums)): | ||||||||||||||||||||||||||
| subarray_sum = 0 | ||||||||||||||||||||||||||
| end = begin | ||||||||||||||||||||||||||
| while end < len(nums) and subarray_sum < target: | ||||||||||||||||||||||||||
| subarray_sum += nums[end] | ||||||||||||||||||||||||||
| end += 1 | ||||||||||||||||||||||||||
| if subarray_sum >= target: | ||||||||||||||||||||||||||
| min_length = min(min_length, end - begin) | ||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## 3rd | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ```py | ||||||||||||||||||||||||||
| class Solution: | ||||||||||||||||||||||||||
| def minSubArrayLen(self, target: int, nums: List[int]) -> int: | ||||||||||||||||||||||||||
| assert target > 0 | ||||||||||||||||||||||||||
| min_length = len(nums) + 1 | ||||||||||||||||||||||||||
| subarray_sum = 0 | ||||||||||||||||||||||||||
| left = -1 # exclusive | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 感想: indexに (普段書いているRustだとこれがとってもやりにくい) |
||||||||||||||||||||||||||
| for right in range(len(nums)): | ||||||||||||||||||||||||||
| subarray_sum += nums[right] | ||||||||||||||||||||||||||
| while subarray_sum >= target: | ||||||||||||||||||||||||||
| min_length = min(min_length, right - left) | ||||||||||||||||||||||||||
| left += 1 | ||||||||||||||||||||||||||
| subarray_sum -= nums[left] | ||||||||||||||||||||||||||
| if min_length == len(nums) + 1: | ||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||
| return min_length | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
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.
このケースは解が存在していないケースかと思います。この問題における解なしというのは
sum(nums) < targetのケースなので、この関数の一番始めでチェックしておけばそれ以降は解が存在する前提になり複雑度が減りそうです。またここで判断するケースでも
len(nums) + 1が解なしを意味するというのはぱっと見ではわかりにくいので、math.infなど明らかにおかしいもので初期化しておくとよさそうに思いました。(上記に書いたように解が存在していることをチェックした後であればmin_length = len(nums)のような解となりうる値の中の最大値で初期化するとかもいいかと思います)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.
math.inf, 型がfloatなのがちょっと気になるんですよね...使うメリットはあるので選択肢としてありだとは思いますが。
sum(nums) < targetかを先にチェックするのは、それも手だと思いますがそこでO(n)かかるコストを払うトレードオフをどう見るかですね... (cpythonなので) C実装のsumは速いからいいだろうという考えもまた分かりますが。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)を悪化させる修正ではないので、個人的には可読性を優先するかなというコメントでした。(書かれているとおりトレードオフなので、可読性の向上があまりないと感じていたり、少しでも計算を早めたいという状況であれば、選択は変わると思います)