文章目录
题目
标题和出处
标题:满足条件的子序列数目
难度
7 级
题目描述
要求
给定一个整数数组 nums \texttt{nums} nums 和一个整数 target \texttt{target} target。
返回 nums \texttt{nums} nums 中满足最小元素与最大元素的和小于或等于 target \texttt{target} target 的非空 子序列的数目。由于答案可能非常大,返回答案模 10 9 + 7 \texttt{10}^\texttt{9} + \texttt{7} 109+7 的余数。
示例
示例 1:
输入: nums = [3,5,6,7], target = 9 \texttt{nums = [3,5,6,7], target = 9} nums = [3,5,6,7], target = 9
输出: 4 \texttt{4} 4
解释:有 4 \texttt{4} 4 个子序列满足该条件。
3\] → 3 + 3 ≤ 9 \\texttt{\[3\]} \\rightarrow \\texttt{3} + \\texttt{3} \\le \\texttt{9} \[3\]→3+3≤9
\[3,5\] → 3 + 5 ≤ 9 \\texttt{\[3,5\]} \\rightarrow \\texttt{3} + \\texttt{5} \\le \\texttt{9} \[3,5\]→3+5≤9
\[3,5,6\] → 3 + 6 ≤ 9 \\texttt{\[3,5,6\]} \\rightarrow \\texttt{3} + \\texttt{6} \\le \\texttt{9} \[3,5,6\]→3+6≤9
\[3,6\] → 3 + 6 ≤ 9 \\texttt{\[3,6\]} \\rightarrow \\texttt{3} + \\texttt{6} \\le \\texttt{9} \[3,6\]→3+6≤9
**示例 2:**
输入: nums = \[3,3,6,8\], target = 10 \\texttt{nums = \[3,3,6,8\], target = 10} nums = \[3,3,6,8\], target = 10
输出: 6 \\texttt{6} 6
解释:有 6 \\texttt{6} 6 个子序列满足该条件: \[3\] \\texttt{\[3\]} \[3\]、 \[3\] \\texttt{\[3\]} \[3\]、 \[3,3\] \\texttt{\[3,3\]} \[3,3\]、 \[3,6\] \\texttt{\[3,6\]} \[3,6\]、 \[3,6\] \\texttt{\[3,6\]} \[3,6\]、 \[3,3,6\] \\texttt{\[3,3,6\]} \[3,3,6\]。
**示例 3:**
输入: nums = \[2,3,3,4,6,7\], target = 12 \\texttt{nums = \[2,3,3,4,6,7\], target = 12} nums = \[2,3,3,4,6,7\], target = 12
输出: 61 \\texttt{61} 61
解释:共有 63 \\texttt{63} 63 个非空子序列,其中 2 \\texttt{2} 2 个不满足条件( \[6,7\] \\texttt{\[6,7\]} \[6,7\]、 \[7\] \\texttt{\[7\]} \[7\])。有效子序列总数为 63 − 2 = 61 \\texttt{63} - \\texttt{2} = \\texttt{61} 63−2=61。
#### 数据范围
* 1 ≤ nums.length ≤ 10 5 \\texttt{1} \\le \\texttt{nums.length} \\le \\texttt{10}\^\\texttt{5} 1≤nums.length≤105
* 1 ≤ nums\[i\] ≤ 10 6 \\texttt{1} \\le \\texttt{nums\[i\]} \\le \\texttt{10}\^\\texttt{6} 1≤nums\[i\]≤106
* 1 ≤ target ≤ 10 6 \\texttt{1} \\le \\texttt{target} \\le \\texttt{10}\^\\texttt{6} 1≤target≤106
## 前言
这道题要求计算数组 nums \\textit{nums} nums 中满足最小值与最大值之和不超过 target \\textit{target} target 的非空子序列的数目。当一个子序列的最小值与最大值确定时,在最小值与最大值之间的其余元素是否加入子序列不会影响子序列的最小值与最大值。如果最小值与最大值之间的其余元素有 x x x 个,则当前最小值与最大值确定的子序列个数是 2 x 2\^x 2x,其中 x x x 不超过数组 nums \\textit{nums} nums 的长度。为了快速计算任意 x x x 对应的 2 x 2\^x 2x,需要预计算从 0 0 0 到数组长度的每个整数对应的 2 2 2 的幂。在预计算 2 2 2 的幂之后,再计算满足条件的子序列数目。
## 解法一
### 思路和算法
由于这道题要求计算满足条件的子序列数目,子序列不要求在原数组中连续,因此可以将数组 nums \\textit{nums} nums 按升序排序,然后在排序后的数组中计算满足条件的子序列数目。
将数组 nums \\textit{nums} nums 排序之后,从左到右遍历数组 nums \\textit{nums} nums,对于下标 i i i,当 nums \[ i \] × 2 ≤ target \\textit{nums}\[i\] \\times 2 \\le \\textit{target} nums\[i\]×2≤target 时,一定存在下标 j ≥ i j \\ge i j≥i 使得 nums \[ i \] + nums \[ j \] ≤ target \\textit{nums}\[i\] + \\textit{nums}\[j\] \\le \\textit{target} nums\[i\]+nums\[j\]≤target,此时 nums \[ i \] \\textit{nums}\[i\] nums\[i\] 和 nums \[ j \] \\textit{nums}\[j\] nums\[j\] 可以分别作为满足条件的子序列中的最小值和最大值。
由于数组 nums \\textit{nums} nums 按升序排序,因此当 nums \[ i \] × 2 ≤ target \\textit{nums}\[i\] \\times 2 \\le \\textit{target} nums\[i\]×2≤target 时,对于下标 i i i 可以使用二分查找的做法找到满足 j ≥ i j \\ge i j≥i 且 nums \[ i \] + nums \[ j \] ≤ target \\textit{nums}\[i\] + \\textit{nums}\[j\] \\le \\textit{target} nums\[i\]+nums\[j\]≤target 的最大下标 j j j。二分查找的下界和上界分别记为 low \\textit{low} low 和 high \\textit{high} high,初始时 low \\textit{low} low 位于下标 i i i, high \\textit{high} high 位于数组的最大下标,每次查找取 mid \\textit{mid} mid 为 low \\textit{low} low 和 high \\textit{high} high 的平均数向上取整,执行如下操作。
* 如果 nums \[ mid \] ≤ target \\textit{nums}\[\\textit{mid}\] \\le \\textit{target} nums\[mid\]≤target,则最大下标大于等于 mid \\textit{mid} mid,因此在下标范围 \[ mid , high \] \[\\textit{mid}, \\textit{high}\] \[mid,high\] 中继续查找。
* 如果 nums \[ mid \] \> target \\textit{nums}\[\\textit{mid}\] \> \\textit{target} nums\[mid\]\>target,则最大下标小于 mid \\textit{mid} mid,因此在下标范围 \[ low , mid − 1 \] \[\\textit{low}, \\textit{mid} - 1\] \[low,mid−1\] 中继续查找。
当 low = high \\textit{low} = \\textit{high} low=high 时,查找结束,此时 low \\textit{low} low 为满足 j ≥ i j \\ge i j≥i 且 nums \[ i \] + nums \[ j \] ≤ target \\textit{nums}\[i\] + \\textit{nums}\[j\] \\le \\textit{target} nums\[i\]+nums\[j\]≤target 的最大下标 j j j。
当 nums \[ i \] \\textit{nums}\[i\] nums\[i\] 是子序列中的最小值时, nums \[ i \] \\textit{nums}\[i\] nums\[i\] 必须在子序列中出现,满足条件的子序列中的最大值可以是大于等于 nums \[ i \] \\textit{nums}\[i\] nums\[i\] 且小于等于 nums \[ j \] \\textit{nums}\[j\] nums\[j\] 的任意值,对于任意 i \< k ≤ j i \< k \\le j i\