1. 问题背景与核心概念
这道题目属于典型的数组操作与组合数学结合的算法问题。给定一个整数数组和一个目标值,要求统计所有满足"最小元素与最大元素之和小于等于目标值"的子序列数量。子序列的定义是原数组中不连续的元素序列,这与子数组(要求连续)有本质区别。
在实际编程面试中,这类问题经常出现在大厂的中高级算法岗位考察中。它综合考察了候选人对以下能力的掌握:
- 双指针技巧的灵活运用
- 组合数学的快速计算能力
- 边界条件的处理意识
- 算法优化的思考深度
注意:子序列与子数组的区分至关重要。例如数组[1,2,3]的子序列包括[1,3]这样不连续的元素,而子数组只能是[1,2]或[2,3]这样的连续片段。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力解法与复杂度分析
最直观的解法是枚举所有可能的子序列,然后检查每个子序列是否满足条件。对于一个长度为n的数组,子序列总数是2^n(每个元素都有选或不选两种可能)。
python复制def countSubsequences(nums, target):
n = len(nums)
count = 0
for mask in range(1, 1<<n): # 枚举所有非空子序列
sub = [nums[i] for i in range(n) if (mask >> i) & 1]
if min(sub) + max(sub) <= target:
count += 1
return count
这种解法的时间复杂度是O(n * 2^n),当n=20时运算量已经超过百万,完全无法应对常规的算法题数据范围(通常n在10^5量级)。我们需要更高效的算法。
3. 双指针优化思路
关键观察点在于:如果将数组排序,对于任意固定的最小值nums[i],要找到最大的nums[j]使得nums[i]+nums[j]<=target。此时所有以nums[i]为最小值,最大值不超过nums[j]的子序列都满足条件。
具体步骤:
- 将数组升序排序
- 初始化两个指针i=0(最小值),j=len(nums)-1(最大值)
- 当nums[i] + nums[j] > target时,j--(缩小最大值)
- 否则,统计i到j之间的
