Leetcode 1498. 满足条件的子序列数目

1.题目基本信息

1.1.题目描述

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

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

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

1.2.题目地址

https://leetcode.cn/problems/number-of-subsequences-that-satisfy-the-given-sum-condition/description/

2.解题方法

2.1.解题思路

遍历第一个元素,以第一个元素为锚,二分查找第二个边界条件

2.2.解题步骤

第一步,将数组进行升序排列

第二步,预处理2的n次方的取模值,应用的原理是(a*b)%MOD=(a%MOD)*(b%MOD)%MOD

第三步,遍历第一个值i,通过二分法找到最后一个j使得numsi+numsj<=target,累加2**(j-i)即为题解(注意取模)

3.解题代码

Python代码

python 复制代码
class Solution:
    # 遍历第一个元素,以第一个元素为锚,二分查找第二个边界条件
    def numSubseq(self, nums: List[int], target: int) -> int:
        length=len(nums)
        # 第一步,将数组进行升序排列
        nums.sort()
        # 第二步,预处理2的n次方的取模值,应用的原理是(a*b)%MOD=[(a%MOD)*(b%MOD)]%MOD
        modVal=10**9 + 7
        power2ModArr=[0]*length
        power2ModArr[0]=1
        for i in range(1,len(power2ModArr)):
            power2ModArr[i]=power2ModArr[i-1]*2%modVal
        # print(power2ModArr)
        # 第三步,遍历第一个值i,通过二分法找到最后一个j使得nums[i]+nums[j]<=target,累加2**(j-i)即为题解(注意取模)
        result=0
        for i in range(length):
            if nums[i]*2>target:
                break
            # 二分找到最后一个j使得nums[i]+nums[j]<=target
            # 红:nums[i]+nums[j]<=target处,蓝:大于target;左闭右闭:left-1始终指向红色,right+1始终指向蓝色。最终的right即为需要找到的j
            left,right=i,length-1
            while left<=right:
                mid=(right-left)//2+left
                if nums[i]+nums[mid]<=target:
                    left=mid+1
                else:
                    right=mid-1
            if right>=i:
                result+=power2ModArr[right-i]
        return result%modVal

C++代码

cpp 复制代码
class Solution {
public:
    int numSubseq(vector<int>& nums, int target) {
        int length=nums.size();
        sort(nums.begin(),nums.end());
        int modVal=1E9+7;
        vector<int> power2ModArr(length,0);
        power2ModArr[0]=1;
        for(int i=1;i<length;++i){
            power2ModArr[i]=power2ModArr[i-1]*2%modVal;
        }
        long long result=0;
        for(int i=0;i<length;++i){
            if(nums[i]*2>target){
                break;
            }
            int left=1,right=length-1;
            while(left<=right){
                int mid=(right-left)/2+left;
                if(nums[i]+nums[mid]<=target){
                    left=mid+1;
                }else{
                    right=mid-1;
                }
            }
            if(right>=i){
                result+=power2ModArr[right-i];
            }
        }
        return result%modVal;
    }
};

4.执行结果

相关推荐
Nuanyt20 小时前
LeetCode Hot 100 链表专题(四)· 3 题(Java)
java·算法·leetcode·链表·双指针
灯澜忆梦20 小时前
LeetCode 1861. 旋转盒子|Go 双指针解法
算法
软件派21 小时前
生产动态数据智能风控:阈值判别、趋势预测、异常识别算法工程落地实战
前端·数据库·算法
ZhengEnCi1 天前
模型训练完整流程:从数据准备到模型上线的 10 个关键步骤(全文可跑)
后端·算法
吞下星星的少年·-·1 天前
Div.3 CF 1131A题(排序,模拟)
算法·模拟·排序
圣保罗的大教堂1 天前
leetcode 453. 最小操作次数使数组元素相等 中等
leetcode
aichitang20241 天前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码1 天前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-1 天前
两数之和-C++实现
c++·算法