アルゴリズムは毎日1題を練習します:積はKのサブ配列より小さいです
713.積がKより小さいサブ配列
正の整数配列numsが与えられます.
この配列内の積がkより小さい連続するサブ配列の個数を探し出す.例1: 入力:nums=[10,5,2,6],k=100出力:8解釈:8個の積が100未満のサブ配列はそれぞれ:[10],[5],[2],[6],[10,5],[5,2],[2,6],[5,26],[5,26]である.[10,5,2]は、積が100未満のサブ配列ではないことに注意されたい.
説明:
リンク:https://leetcode-cn.com/problems/subarray-product-less-than-k
問題解分析題の要求出力は、サブ配列の個数であり、サブ配列の要素は連続的であり、積はk 以下であり、k に等しくない.単一要素の配列も許容されるが、その値はk 未満である.は、まず調整を満たすサブ配列を見つけてから、数を統計する.サブ配列list を維持する必要はありません要点はすべてのサブ配列を見つけることです. は順次遍歴し、いずれかのiの値がkより小さい場合count+=1 連続性判定は、j=i,jを右に移動する
方法2:ダブルポインタ分析 二分ルックアップを用いてこの問題を解決することができ,すなわち,固定iに対して,二分ルックアップはnums[i]からnums[j]までの最大jの積がk未満であることを見出した.しかし、積が非常に大きい(最悪の場合1000^50000に達すると数値オーバーフローを招く可能性があるため、nums配列に対して対数を取り、乗算を加算、すなわちlog(∏inums[i])=Σilognums[i]に変換する必要があり、数値オーバーフローの問題は発生しない.アルゴリズム numsの各数に対して対数を取った後,その接頭辞とprefix,すなわちprefix[i+1]=Σnums[x]を格納し,二分ルックアップ時にiとjに対してprefix[j+1]−prefix[i]でnums[i]からnums[j]の積の対数を得ることができる.固定iの場合、最大の条件を満たすjが見つかった後、j−i+1個の積がk未満の連続サブ配列を含む.
正の整数配列numsが与えられます.
この配列内の積がkより小さい連続するサブ配列の個数を探し出す.
説明:
0 < nums.length <= 50000
0 < nums[i] < 1000
0 <= k < 10^6
リンク:https://leetcode-cn.com/problems/subarray-product-less-than-k
問題解分析
#
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
if not nums:
return None
count = 0
length = len(nums)
for i in range(0,length):
if nums[i] < k:
count += 1
j = i + 1
mult = nums[i]
while j < length:
mult *= nums[j]
if mult < k:
count += 1
j += 1
else:
break
return count
方法2:ダブルポインタ
#
class Solution:
def numSubarrayProductLessThanK(self, nums, k):
if k <= 1: return 0
mult = 1
count = left = 0
for right, val in enumerate(nums):
mult *= val
while mult >= k:
mult /= nums[left]
left += 1
count += right - left + 1
return count