加载中...
1498-满足条件的子序列数目(Number of Subsequences That Satisfy the Given Sum Condition)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.1k | 阅读时长: 5分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/number-of-subsequences-that-satisfy-the-given-sum-condition

英文原文

Given an array of integers nums and an integer target.

Return the number of non-empty subsequences of nums such that the sum of the minimum and maximum element on it is less or equal to target. Since the answer may be too large, return it modulo 109 + 7.

 

Example 1:

Input: nums = [3,5,6,7], target = 9
Output: 4
Explanation: There are 4 subsequences that satisfy the condition.
[3] -> Min value + max value <= target (3 + 3 <= 9)
[3,5] -> (3 + 5 <= 9)
[3,5,6] -> (3 + 6 <= 9)
[3,6] -> (3 + 6 <= 9)

Example 2:

Input: nums = [3,3,6,8], target = 10
Output: 6
Explanation: There are 6 subsequences that satisfy the condition. (nums can have repeated numbers).
[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6]

Example 3:

Input: nums = [2,3,3,4,6,7], target = 12
Output: 61
Explanation: There are 63 non-empty subsequences, two of them don't satisfy the condition ([6,7], [7]).
Number of valid subsequences (63 - 2 = 61).

Example 4:

Input: nums = [5,2,4,1,7,6,8], target = 16
Output: 127
Explanation: All non-empty subset satisfy the condition (2^7 - 1) = 127

 

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 106
  • 1 <= target <= 106

中文题目

给你一个整数数组 nums 和一个整数 target

请你统计并返回 nums 中能满足其最小元素与最大元素的 小于或等于 target非空 子序列的数目。

由于答案可能很大,请将结果对 10^9 + 7 取余后返回。

 

示例 1:

输入: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)

示例 2:

输入:nums = [3,3,6,8], target = 10
输出:6
解释:有 6 个子序列满足该条件。(nums 中可以有重复数字)
[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6]

示例 3:

输入:nums = [2,3,3,4,6,7], target = 12
输出:61
解释:共有 63 个非空子序列,其中 2 个不满足条件([6,7], [7])
有效序列总数为(63 - 2 = 61)

示例 4:

输入:nums = [5,2,4,1,7,6,8], target = 16
输出:127
解释:所有非空子序列都满足条件 (2^7 - 1) = 127

 

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6
  • 1 <= target <= 10^6

通过代码

高赞题解

这题一开始我打leetcode周赛的时候用的回溯算法,结果时间超了,那么表示暴力法是过不了的,所以这题需要找规律,然后用数学的方式解决。

思路:该题目只需要子数组的最小值+最大值<=target,因此,如果有个滑动窗口,滑动窗口内的最小值+最大值小于等于target的话,那么这个子数组进行排列组合,在包含最小值的情况下,排列组合的结果都符合题意。

如:用list=[min,num1,num2,num3,num4,max]表示min+max<=target的滑动窗口,这里n=len(list),n==6,包含最小值的子数组为:
[min]、[min,num1]、[min,num2]、[min,num1,num2,num3]、[min,num1,max]等等,这样的子数组有2^(n-1)个。(即[num1,num2,num3,num4,max]的全排列(2^(n-1))-1个,加上只有[min]的子数组,加起来共2^(n-1)个)

由上我们可知,我们需要首先对数组进行从小到大排序,使用双指针找到满足条件的每一对最小值和最大值,累加滑动窗口的排列组合数量就可以了。

如:经排序后的数组为[num1,num2,num3,num4,num5,num6],output=0,双指针的索引left=0 right=5

第一步,若 num1+num5<=targer,这里num1和num5是一对最小值和最大值,output=output+2^4

第二步,双指针向内移动,left=left+1 -> num2+num5>target -> right=right-1 -> num2+num4<=target, 这里num2和num4 是一对最小值和最大值, output=output+2^2

如此迭代至 left>right 的时候,即可结束。

具体代码如下

class Solution:
    def numSubseq(self, nums: List[int], target: int) -> int:
        nums.sort()
        if nums[0] * 2 > target:
            return 0
            
        left = 0
        right = len(nums) - 1
        res = 0
        while left <= right:
            if nums[left] + nums[right] <= target:
                res += 2**(right-left)
                left += 1
            else:
                right -= 1
        return res%(10**9+7)

8000ms居然都过了,我原来的回溯真不知道要多久。。

image.png

统计信息

通过次数 提交次数 AC比率
5439 16259 33.5%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1497-检查数组对是否可以被 k 整除(Check If Array Pairs Are Divisible by k)
下一篇:
1499-满足不等式的最大值(Max Value of Equation)
本文目录
本文目录