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

题目:

思路:

【1】首先是明确约束

1)「子序列」是不要求连续的;
2)只关心这个子序列的最小值和最大值,而不关心元素的相对顺序;

代码展示:

//时间32 ms 击败 75.71%
//内存53.1 MB 击败 79.10%
class Solution {
    public int numSubseq(int[] nums, int target) {
        Arrays.sort(nums);
        int n = nums.length;
        int mod = 1000000007;
        int[] dp = new int[n];
        dp[0] = 1;
        for (int i = 1; i < n; i++) {
            dp[i] = (dp[i - 1] << 1) % mod;
        }
        int res = 0;
        for (int left = 0, right = n - 1; left <= right; ) {
            if (nums[left] + nums[right] <= target) {
                res = (res + dp[right - left]) % mod;
                left++;
            } else {
                right--;
            }
        }
        return res;
    }
}

//时间92 ms 击败 5.65%
//内存54 MB 击败 30.51%
class Solution {
    static final int P = 1000000007;
    static final int MAX_N = 100005;

    int[] f = new int[MAX_N];

    public int numSubseq(int[] nums, int target) {
        pretreatment();

        Arrays.sort(nums);

        int ans = 0;
        for (int i = 0; i < nums.length && nums[i] * 2 <= target; ++i) {
            int maxValue = target - nums[i];
            int pos = binarySearch(nums, maxValue) - 1;
            int contribute = (pos >= i) ? f[pos - i] : 0;
            ans = (ans + contribute) % P;
        }

        return ans;
    }

    public void pretreatment() {
        f[0] = 1;
        for (int i = 1; i < MAX_N; ++i) {
            f[i] = (f[i - 1] << 1) % P;
        }
    }

    public int binarySearch(int[] nums, int target) {
        int low = 0, high = nums.length;
        while (low < high) {
            int mid = (high - low) / 2 + low;
            if (mid == nums.length) {
                return mid;
            }
            int num = nums[mid];
            if (num <= target) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }
}

 

posted @ 2023-08-17 16:28  忧愁的chafry  阅读(16)  评论(0编辑  收藏  举报