diff --git a/209.Minimum-Size-Subarray-Sum/memo.md b/209.Minimum-Size-Subarray-Sum/memo.md new file mode 100644 index 0000000..6cc9a4c --- /dev/null +++ b/209.Minimum-Size-Subarray-Sum/memo.md @@ -0,0 +1,21 @@ +# 209. Minimum Size Subarray Sum + +- sol1.py: 何も見ないで書いた。sliding windowで解ける。O(n)。 + +https://github.com/SuperHotDogCat/coding-interview/pull/31/changes + +二重のwhile文で書いている。rightの始まりと終わりは確定しているので、個人的にはfor文が良いのではないかと思った。 +min_length = len(nums) + 1とするのはなるほど。ただ分かりやすさではinfでも悪くはないと思う。 + +https://github.com/olsen-blue/Arai60/pull/50/changes/BASE..1b460a0c97f2ef17efe579db6835cb0623d6cf67#diff-6d4eb2707ed57d8037bfa2e5985424b237a407741a7602ba92b31e090d1cb096 + +https://github.com/naoto-iwase/leetcode/pull/50 + +二分探索と分割統治法で書く。計算量はO(nlogn)になる +二分探索 -> 自分で書くと、leftのindexの処理が彼と異なった。leftを含めるか否か。 + +二分探索の方は自分でも思いついただろう(今回は人の答えを見たが) +分割統治法は人のを見て初めて気づいたので、頭に入れておきたい + + + diff --git a/209.Minimum-Size-Subarray-Sum/sol1.py b/209.Minimum-Size-Subarray-Sum/sol1.py new file mode 100644 index 0000000..6768dfd --- /dev/null +++ b/209.Minimum-Size-Subarray-Sum/sol1.py @@ -0,0 +1,18 @@ +import math + + +class Solution: + def minSubArrayLen(self, target: int, nums: List[int]) -> int: + left = 0 + current_sum = 0 + min_subarray_len = float("inf") + for right, num_right in enumerate(nums): + current_sum += num_right + if current_sum < target: + continue + while left < len(nums) and current_sum - nums[left] >= target: + current_sum -= nums[left] + left += 1 + min_subarray_len = min(min_subarray_len, right - left + 1) + + return 0 if math.isinf(min_subarray_len) else min_subarray_len diff --git a/209.Minimum-Size-Subarray-Sum/sol2.py b/209.Minimum-Size-Subarray-Sum/sol2.py new file mode 100644 index 0000000..b16dbe1 --- /dev/null +++ b/209.Minimum-Size-Subarray-Sum/sol2.py @@ -0,0 +1,15 @@ +import itertools +import bisect +import math + + +class Solution: + def minSubArrayLen(self, target: int, nums: List[int]) -> int: + left = 0 + min_subarray_len = float("inf") + prefix_sum = list(itertools.accumulate(nums)) + for left, num_left in enumerate(nums): + right = bisect.bisect_left(prefix_sum, target + prefix_sum[left] - num_left) + if right < len(nums): + min_subarray_len = min(min_subarray_len, right - left + 1) + return 0 if math.isinf(min_subarray_len) else min_subarray_len diff --git a/209.Minimum-Size-Subarray-Sum/sol3.py b/209.Minimum-Size-Subarray-Sum/sol3.py new file mode 100644 index 0000000..60c7edb --- /dev/null +++ b/209.Minimum-Size-Subarray-Sum/sol3.py @@ -0,0 +1,42 @@ +import math + + +class Solution: + def minSubArrayLen(self, target: int, nums: List[int]) -> int: + def devide_and_conquer(left, right): + if left > right: + return float("inf") + if left == right: + return float("inf") if nums[left] < target else 1 + mid = left + (right - left) // 2 + return min( + devide_and_conquer(left, mid), + devide_and_conquer(mid + 1, right), + cross_middle(left, right, mid, target), + ) + + def cross_middle(left, right, mid, target): + if mid >= len(nums): + return float("inf") + left_cross = mid + right_cross = mid + 1 + min_length = float("inf") + current_sum = nums[left_cross] + nums[right_cross] + while right_cross <= right: + while current_sum < target and left_cross > left: + left_cross -= 1 + current_sum += nums[left_cross] + if current_sum >= target: + min_length = min(min_length, right_cross - left_cross + 1) + right_cross += 1 + if right_cross > right: + continue + current_sum += nums[right_cross] + while current_sum >= target and left_cross < mid: + current_sum -= nums[left_cross] + left_cross += 1 + + return min_length + + min_length = devide_and_conquer(0, len(nums) - 1) + return 0 if math.isinf(min_length) else min_length