1. 题目解析与解题思路
1.1 问题重述
给定一个整数数组 nums 和一个整数 target,要求计算数组中满足最小元素与最大元素的和小于或等于 target 的非空子序列的数目。由于结果可能非常大,需要对结果取模 10^9 + 7。
子序列的定义是不需要连续的元素,但需要保持原始顺序。例如对于数组 [3,5,6,7],[3,6] 是一个有效的子序列,而 [6,3] 则不是。
1.2 关键观察点
- 子序列特性:子序列的最小值和最大值决定了其是否满足条件,中间元素的选择不影响条件判断
- 幂次计算:对于确定的 min 和 max,中间有 x 个元素时,有 2^x 种可能的子序列组合
- 排序优势:将数组排序后可以更高效地找到满足条件的子序列范围
1.3 解题思路演变
初始思路可能是暴力枚举所有子序列,但时间复杂度为 O(2^n),对于 n=10^5 的数据规模完全不适用。通过分析子序列特性,我们发现:
- 排序后可以更方便地确定最小值和最大值的范围
- 对于每个最小值 nums[i],可以找到最大的 nums[j] 使得 nums[i]+nums[j]<=target
- 中间元素的组合数可以通过预计算 2 的幂次来快速获取
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解法一:排序+二分查找
2.1 算法设计
-
预处理阶段:
- 对数组进行排序(O(nlogn))
- 预计算 2 的幂次数组(O(n)),用于快速获取组合数
-
核心计算:
- 遍历每个元素作为最小值候选(O(n))
- 对每个 nums[i],使用二分查找找到最大的 j 满足 nums[i]+nums[j]<=target(O(logn))
- 计算以 nums[i] 为最小值的有效子序列数:2^(j-i)
-
结果处理:
- 累加所有有效子序列数
- 对结果取模
2.2 代码实现详解
java复制class Solution {
static final int MODULO = 1000000007;
public int numSubseq(int[] nums, int target) {
int
