2020/05/15 每日一題
對於要求連續子陣列的題目,靈活使用字首和和滑窗的方法。特點在於,字首和是否遞增。
題目需要注意幾個關鍵點,陣列元素是既有正數又有負數的,且要求是連續的子陣列。
陣列元素既有正數又有負數隱含了意思,陣列不是單調的。因此不適合用滑動視窗的方法。**滑窗特點是,固定了左邊界以後,右邊界找到了乙個可行解以後,右邊界再靠右邊的更大的區間肯定不存在目標值,所以才將左邊界繼續向右滑。**在這道題裡顯然沒有這個性質。
其次,這裡的連續子陣列的限制給了我們採用字首和的空間。我們儲存字首和進行比較即可。
要求presum[i]-k = presum[j]
也就是存在[j+1,i]
這個子區間的和為k。
class
solution
:def
subarraysum
(self, nums: list[
int]
, k:
int)
->
int:
## 看到陣列中有連續子陣列,因此考慮字首和的思路
dic = collections.defaultdict(
int)
dic[0]
=1sum_ =
0 ans =
0for num in nums:
sum_ += num
if sum_ - k in dic:
ans += dic[sum_-k]
# 這裡需要注意,先判斷再存入當前的數值。否則可能出現問題
和上面題目很相似的題目,但是特點在於上一題是查詢到特定的數值即可。這道題目的要求是得到被k整除。因此我們雖然採用字首和的思路,但是記錄的並不是字首和,而是字首和對k取餘的結果。
注意負數的同餘,-2%6 = 4
,這裡不需要額外的處理。
class
solution
:def
subarraysdivbyk
(self, a: list[
int]
, k:
int)
->
int:
# dic儲存被5除完的餘數
這道題目就存在顯著的不同了,首先要求的了是正整數,也就是實現了字首和是單調的。但是要求查詢的難度變大了,需要找出小於某一數值的字首和,所以再採用字首和的思路就複雜度增加了,每次需要遍歷所有的字首和,才能找全符合小於的數字。
但是我們知道了單調的特性,就可以採用滑動視窗的方法,固定左側,每次向右側擴張。如果超過了,就移動左側邊界。
兩個細節:
如何統計合理解?採用right-left+1
,也就是固定了右側時,我們可以移動左側界,得到的全都是合理解。
移動左側邊界的方法。我們需要每次移動左側邊界最多移動到大於右側乙個,這樣可以幫助右側處理掉某乙個元素自身就大於bar的情況。
class
solution
:def
numsubarrayproductlessthank
(self, nums: list[
int]
, k:
int)
->
int:
# 對於這種單調增的序列,可以採用滑動視窗的方法
n =len(nums)
right =
0 left =
0 cur =
1 ans =
0for right, num in
enumerate
(nums)
: cur *= num
while cur>=k and left<=right:
cur /= nums[left]
left +=
1 ans += right-left+
1return ans
letcode每日一題 分割陣列為連續子串行
題目描述如下 對於陣列中的元素 x,如果存在乙個子串行以 x 1 結尾,則可以將 x加入該子串行中。將 x 加入已有的子串行總是比新建 乙個只包含 x 的子串行更優,因為前者可以將乙個已有的子串行的長度增加 1,而後者新建乙個長度為 1 的子串行,而題 目要求分割成的子串行的長度都不小於 3,因此應...
leetcode每日一題5 15和為K的子陣列
給定乙個整數陣列和乙個整數 k,你需要找到該陣列中和為 k 的連續的子陣列的個數。示例 1 輸入 nums 1,1,1 k 2 輸出 2 1,1 與 1,1 為兩種不同的情況。說明 陣列的長度為 1,20,000 陣列中元素的範圍是 1000,1000 且整數 k 的範圍是 1e7,1e7 思路 這...
字首和 和為k的連續子陣列
給定乙個整數陣列和乙個整數k,你需要找到該陣列中和為k的連續的子陣列的個數。示例輸入 nums 1,1,1 k 2 輸出 2 1,1 與 1,1 為兩種不同的情況。此題暴力法則為求出每一段連續的子陣列的和,然後遍歷這些和求出和為k的陣列個數 一段連續的數必然有乙個左邊界和乙個右邊界,所以只要列舉所有...