一、Problem
給你一個整數數組 nums 和一個整數 target 。
請你統計並返回 nums 中能滿足其最小元素與最大元素的 和 小於或等於 target 的 非空 子序列的數目。
由於答案可能很大,請將結果對 10^9 + 7 取餘後返回。
輸入:nums = [3,5,6,7], target = 9
輸出:4
解釋:有 4 個子序列滿足該條件。
[3] -> 最小元素 + 最大元素 <= target (3 + 3 <= 9)
[3,5] -> (3 + 5 <= 9)
[3,5,6] -> (3 + 6 <= 9)
[3,6] -> (3 + 6 <= 9)
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6
1 <= target <= 10^6
二、Solution
方法一:雙指針
思路
題目的子序列字樣有點迷惑人,但是仔細想一下會發現其實可以不考慮一組數的順序,所以知道找到了一組合法的數,假設這組數的長度爲 k,那麼一共會有 ,比如(a 是有序的數組):
a = [mi,n1,n2,ma],tar = x
若 mi+mx <= tar,則一定會有 mi + mi < tar;mi+n1 <= tar;mi+n2 < tar,所以以下的子序列都是合法的:
[mi],[mi,n1], [mi, n2], [mi, ma], [mi, n1, n2], [mi, n1, ma], [mi, n2, ma], [mi,n1,n2,ma]
一共 8 個
class Solution {
public int numSubseq(int[] a, int tar) {
Arrays.sort(a);
if (a[0]*2 > tar)
return 0;
int n = a.length, ans = 0, l = 0, r = n-1, mod = (int) 1e9+7;
while (l <= r) {
if (a[l] + a[r] > tar) {
r--;
} else {
ans = (ans + (int) Math.pow(2, r-l)) % mod;
l++;
}
}
return ans;
}
}
溢出問題:當 r-l 很大時,會造成整形溢出,怎麼解決呢?比賽的時候我是換成了 python,事後發現有兩種方案可以解決問題:
- 用快速冪 + 同餘來避免溢出
- 利用同餘預處理一個長度爲 n 的2的冪次方數數組
class Solution {
public int numSubseq(int[] a, int tar) {
Arrays.sort(a);
if (a[0]*2 > tar)
return 0;
int n = a.length, ans = 0, l = 0, r = n-1, mod = (int) 1e9+7, pow[] = new int[n];
pow[0] = 1;
for (int i = 1; i < n; i++)
pow[i] = (pow[i-1] << 1) % mod;
while (l <= r) {
if (a[l] + a[r] > tar) {
r--;
} else {
ans = (ans + pow[r-l]) % mod;
l++;
}
}
return ans;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,