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次方的取模值,应用的原理是(ab)%MOD=[(a%MOD)(b%MOD)]%MOD

第三步,遍历第一个值i,通过二分法找到最后一个j使得nums[i]+nums[j]<=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.执行结果

相关推荐
旺仔老馒头.15 分钟前
【数据结构与算法】手撕排序算法(二)
c语言·数据结构·算法·排序算法
好学且牛逼的马27 分钟前
【Hot100 | 2 LeetCode49 字母异位词分组问题】
算法
2301_7951672038 分钟前
Rust 在内存安全方面的设计方案的核心思想是“共享不可变,可变不共享”
算法·安全·rust
czhc11400756631 小时前
Java117 最长公共前缀
java·数据结构·算法
java 乐山1 小时前
蓝牙网关(备份)
linux·网络·算法
云泽8081 小时前
快速排序算法详解:hoare、挖坑法、lomuto前后指针与非递归实现
算法·排序算法
数字化脑洞实验室1 小时前
智能决策算法的核心原理是什么?
人工智能·算法·机器学习
流烟默1 小时前
机器学习中拟合、欠拟合、过拟合是什么
人工智能·算法·机器学习
Brianna Home1 小时前
现代C++:从性能泥潭到AI基石
开发语言·c++·算法
再卷也是菜1 小时前
算法基础篇(10)递归型枚举与回溯剪枝
算法·深度优先·剪枝