Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 2552. Count Increasing Quadruplets

Woodyiiiiiii opened this issue · comments

这道题是典型的三元/四元组题型,一般这种题型的解法,要满足合理的时间复杂度,我总结

  1. 从中间索引出发
  2. 对边缘索引预处理DP

这题的条件有:

  1. 0 <= i < j < k < l < nnums[i] < nums[k] < nums[j] < nums[l]
  2. 1 <= nums[i] <= nums.length
  3. 隐藏条件:4 <= nums.length <= 4000,暗示要用O(n^2)或者O(n^2lgn)

照例从j和k出发,两次循环后定位j和k,那么如何找到i和l呢?这就要预处理DP了。我们用prefix表示i/nums[i]的数目,用suffix表示l/nums[l]的数目,利用有限元素(1<=nums[i]<=n) 的条件。详情看代码如何DP:

class Solution {
    public long countQuadruplets(int[] nums) {
        int n = nums.length;
        // 表示i/nums[i]的数目
        long[] prefix = new long[n + 1];
        // 表示l/nums[l]的数目
        // 预处理l
        long[][] suffix = new long[n][n + 1];
        for (int l = n - 1; l >= 0; --l) {
            for (int r = 1; r < nums[l]; ++r) {
                suffix[l][r]++;
            }
            if (l > 0) {
                System.arraycopy(suffix[l], 0, suffix[l - 1], 0, n + 1);
            }
        }

        long ans = 0;
        for (int i = 0; i < n; ++i) {
            // j
            if (i > 0 && i < n - 1) {
                int j = i;
                for (int k = j + 1; k < n - 1; ++k) {
                    if (nums[k] < nums[j]) {
                        ans += prefix[nums[k]] * suffix[k + 1][nums[j]];
                    }
                }
            }
            // 处理i
            for (int v = nums[i] + 1; v <= n; ++v) {
                prefix[v]++;
            }
        }
        return ans;
    }
}

类似三元/四元组题目: