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

2023-10-14 05:40

本文主要是介绍Leetcode: 1498. 满足条件的子序列数目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

给你一个整数数组 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


分析

首先这个题目情景会让人想到回溯法,但是回溯法的算法复杂度过大,因为它实际是搜索了所有的情况再进行判断。

因为对一个子序列来说,我们只关心它的最小值和最大值,所以原序列中元素的顺序可以任意改变,当然也可以排序

对于序列 [1, 2, 3], 它的子序列是 {[1], [1, 2], [1, 3], [1, 2, 3], [2], [2, 3], [3]}, 可以拆成 7 =  2^2 + 2^1 + 2^0, 分别对应 {[1], [1, 2], [1, 3], [1, 2, 3]}, {[2], [2, 3]},{[3]}。

设 [left, right] 表示一个子序列,只要 nums[left] + nums[right] <= target, 那么它产生的包含 nums[left] 的序列都是合法的,有2^{right - left} 个。

比如:对序列 [1, 2, 3], target = 6,nums[0] + nums[2] <= 6, 包含 nums[0] = 1 的序列有 2^{2- 0} = 4 个;nums[1] + nums[2] <= 6, 包含 nums[1] = 2 的序列有 2^{2- 1} = 2 个;nums[2] + nums[2] <= 6, 包含 num[2] = 3, 的序列有 2^{2 - 2} = 1个。

分析到这里,可以利用双指针来解决这个问题:

  1. 初始化 left = 0, right = nums.length -1, ans = 0
  2. 当 left <= right 时:
  •  如果 nums[left] + nums[right] <= target:
    • 给 ans 加 2^{right - left}
    • left++
  • 如果 nums[left] + nums[right] > target
    • right--

代码

class Solution {public int numSubseq(int[] nums, int target) {Arrays.sort(nums);int mod = 1000000007;int[] pow = new int[(int) Math.pow(10, 5) + 1];pow[0] = 1;for (int i = 1; i < pow.length; i++) {pow[i] = (pow[i - 1] * 2) % mod;}int ans = 0;int left = 0, right = nums.length - 1;while (left <= right) {if (nums[left] + nums[right] <= target) {ans = (ans + pow[right - left]) % mod;left++;} else {right--;}}return ans;}
}

注意:2^n 可能会很大,所以提前打表。

这篇关于Leetcode: 1498. 满足条件的子序列数目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/208538

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr