LintCode 1529: Triplet Subarray With Absolute Diff Less Than or Equal to Limit (同向双指针经典题)

本文介绍了一种高效算法,用于在给定的整数数组中找出所有满足特定条件的三元子数组,即任意两个元素之间的绝对差小于等于预设限制。通过使用双指针技巧,该算法能够在O(n)的时间复杂度内解决问题。

1529. Triplet Subarray With Absolute Diff Less Than or Equal to Limit

Given an increasing array of integers nums and an integer limit, return the number of the triplet subarray in which the absolute difference between any two elements is less than or equal to limit.

In case there is no subarray satisfying the given condition return 0.

Example

Example 1:

Input:[1, 2, 3, 4], 3
Output:4
Explanation:We can choose (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4). Therefore, the number of the triplet subarray is 4.

Example 2:

Input: [1, 10, 20, 30, 50], 19
Output:1
Explanation:The only triplet array is (1, 10, 20), so the answer is 1。

Challenge

Can you figure out a solution with time complexity of O(n)?

Notice

1 ≤ len(nums) ≤ 1e4,1 ≤ limit ≤ 1e6,0 ≤ nums[i] ≤ 1e6
Since the answer may be too large, return it modulo 99997867.

Input test data (one parameter per line)How to understand a testcase?


解法1:这题本来可以用DP,但DP可能要O(N^2),而这里数据量太大,所以采用双指针。

思路,p2先行。当nums[p2]-nums[p1]>limit时,说明p1..p2这个range还不符合要求,所以p1必须++,当p1符合条件后跳出while循环,此时我们可以看出,p1, p1+1, ... p2这个range,p2固定,p1..p2-1里面任取2数都可以满足3数之中任意之差的绝对值<=limit,所以count+=((p2 - p1) * (p2 - p1 - 1) / 2)。这里采用组合C(x,2)的算法。

注意中间要取模。

class Solution {
public:
    /**
     * @param nums: the given array
     * @param limit: the limit on the absolute difference of the subarray
     * @return: Find the number of triplet subarray with the absolute difference less than or equal to limit
     */
    int tripletSubarray(vector<int> &nums, int limit) {
        int len = nums.size();
        long long count = 0;
        int p1 = 0, p2 = 0;
        
        for (int p2 = 2; p2 < len; ++p2) {
            while(nums[p2] - nums[p1] > limit) {
                p1++;
            }
            count += ((p2 - p1) * (p2 - p1 - 1) / 2) % 99997867;
        }
        return count;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值