🔗 🟡 3101. Count Alternating Subarrays 1405

tags: Weekly Contest 391 陣列(Array) 數學(Math) 動態規劃(DP)

題意

給定一個二進位制陣列 numsnums

如果一個子陣列中 相鄰 的兩個元素值 不相同 ,我們就稱其為 交替的(alternating)

返回 numsnums 中交替子陣列的數量。

思路

方法一:動態規劃(DP)

dp[i]dp[i] 表示以 nums[i]nums[i] 結尾的交替子陣列的數量,則有以下遞迴式:

  • nums[i]nums[i1]nums[i] \neq nums[i-1],則代表 nums[i]nums[i] 可以繼續接在 nums[i1]nums[i-1] 後面,因此 dp[i]=dp[i1]+1dp[i] = dp[i-1] + 1
  • 否則 dp[i]=1dp[i] = 1 ,因為 nums[i]nums[i] 本身就可以視為一個交替子陣列。

初始化 dpdp 陣列為全 11,從 i=1i=1 開始遍歷 numsnums 陣列,更新 dp[i]dp[i] 和答案 ansans。由於計算時會忽略 i=0i=0 的情況,因此須將答案初始化為 11

複雜度分析

  • 時間複雜度:O(n)O(n),其中 nn 為陣列 numsnums 的長度。
  • 空間複雜度:O(n)O(n),用於存儲 dpdp 陣列。
1
2
3
4
5
6
7
8
9
10
class Solution:
def countAlternatingSubarrays(self, nums: List[int]) -> int:
n = len(nums)
ans = 1
dp = [1] * n
for i in range(1, n):
if nums[i] != nums[i - 1]:
dp[i] = dp[i - 1] + 1
ans += dp[i]
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
long long countAlternatingSubarrays(vector<int>& nums) {
int n = nums.size();
long long ans = 1;
vector<int> dp(n, 1);
for (int i = 1; i < n; i++) {
if (nums[i] != nums[i - 1]) dp[i] = dp[i - 1] + 1;
ans += dp[i];
}
return ans;
}
};

方法二:空間優化

注意到方法一中,我們只需要用到 dp[i]dp[i]dp[i1]dp[i-1] 的值,因此可以將空間複雜度優化至 O(1)O(1)

ff 表示以 nums[i]nums[i] 結尾的交替子陣列的數量,則若 nums[i]nums[i1]nums[i] \neq nums[i-1],則 f=f+1f = f + 1;否則 f=1f = 1 ,並在計算過程中累加 ff 的值至答案中,同樣需將 ansans 初始化為 11

複雜度分析

  • 時間複雜度:O(n)O(n),其中 nn 為陣列 numsnums 的長度。
  • 空間複雜度:O(1)O(1)
1
2
3
4
5
6
7
8
9
10
class Solution:
def countAlternatingSubarrays(self, nums: List[int]) -> int:
ans = f = 1
for x, y in pairwise(nums):
if x != y:
f += 1
else:
f = 1
ans += f
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
long long countAlternatingSubarrays(vector<int>& nums) {
int n = nums.size();
long long ans = 1;
int f = 1;
for (int i = 1; i < n; i++) {
if (nums[i] != nums[i - 1]) f += 1;
else f = 1;
ans += f;
}
return ans;
}
};

寫在最後

Cover photo is remixed from @吃肥皂泡泡, thanks for their work!