LeetCode2552.统计上升四元组

LeetCode2552.统计上升四元组

无意间在b站刷到一个宝藏大神博主的视频讲解这道题,简直太帅,想发个记录下作为笔记
up主:算法大师兄

好了,接下来我们看题目描述:

给你一个长度为 n 下标从 0 开始的整数数组 nums ,它包含 1 到 n 的所有数字,请你返回上升四元组的数目。

如果一个四元组 (i, j, k, l) 满足以下条件,我们称它是上升的:

0 <= i < j < k < l < n 且
nums[i] < nums[k] < nums[j] < nums[l] 。

示例 1:

输入:nums = [1,3,2,4,5]
输出:2
解释:

  • 当 i = 0 ,j = 1 ,k = 2 且 l = 3 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
  • 当 i = 0 ,j = 1 ,k = 2 且 l = 4 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
    没有其他的四元组,所以我们返回 2 。
    示例 2:

输入:nums = [1,2,3,4]
输出:0
解释:只存在一个四元组 i = 0 ,j = 1 ,k = 2 ,l = 3 ,但是 nums[j] < nums[k] ,所以我们返回 0 。

提示:

4 <= nums.length <= 4000
1 <= nums[i] <= nums.length
nums 中所有数字 互不相同 ,nums 是一个排列。

解体思路:

1.先用暴力解法试试,四重循环,只能过几个用例超时严重
class Solution {
public:
    long long countQuadruplets(vector<int>& nums) {
        long long ans = 0;
        int n = nums.size();
        for(int i= 0; i < n; i++)
            for(int j = i + 1; j < n; j++)
                for(int k = j + 1; j < n; k++)
                    for(int l = k + 1; l < n; l++)
                        if(nums[i] < nums[k] < nums[j] < nums[l])
                        ans++;
    return ans;
    }
};
2.中间进在这里插入代码片行判断截胡,省去一部分无用循环,优化
class Solution {
public:
    long long countQuadruplets(vector<int>& nums) {
        long long ans = 0;
        int n = nums.size();
        for(int i= 0; i < n; i++){
            for(int j = i + 1; j < n; j++){
                for(int k = j + 1; k < n; k++){
                    if(nums[i] >= nums[k]) continue;
                    if(nums[k] >= nums[j]) continue;
                    for(int l = k + 1; l < n; l++){
                        if(nums[i] < nums[k] < nums[j] < nums[l])
                        ans++;
                    }
                }
            }
        }
    return ans;
    }
};
3.发现复杂度还是很高,想到优化为O(n^3)复杂度

117 / 121 个通过的测试用例 时间复杂度:O(n^3)
思路: 通过比较 j 和 k 两层循环,然后再进行对 i 和 l的满足条件的数量的记录,
相乘,最终等于是只需要三重循环(第三层里两个循环单独开来)

class Solution {
public:
    long long countQuadruplets(vector<int>& nums) {
        long long ans = 0;
        int n = nums.size();
        for(int j = 1; j < n; j++) {
            for(int k = j + 1; k < n; k++) {
                if(nums[j] <= nums[k]) continue;
                int less = 0;
                for(int i = 0; i < j; i++) {
                    if(nums[i] < nums[k])
                        less += 1;
                }
                int bigger = 0;
                for(int l = k + 1; l < n; l++) {
                    if(nums[j] < nums[l])
                        bigger += 1;
                }
                ans += less * bigger;
            }
        }
        return ans;
    }
};
4.最终AK代码

该函数的目标是统计满足条件的四元组的数量。具体的做法是遍历数组,并使用一个辅助数组cnt来记录以每个元素为中心的上升三元数组的数量。在遍历过程中,通过累加cnt数组中的值,可以得到满足条件的四元组的数量。

整个代码的时间复杂度为O(n^2),其中n是数组的长度。

class Solution {
public:
    long long countQuadruplets(vector<int>& nums) {
        long long ans = 0; // 用于记录满足条件的四元组数量
        int n = nums.size(); // 数组的长度
        int cnt[n]; // 用cnt[j]来记录以j为中心满足条件的上升三元数组的数量
        memset(cnt, 0, sizeof(cnt)); // 将cnt数组初始化为0

        for (int l = 0; l < n; l++) {
            int idx = 0; // 用于记录以l为右边界的上升三元数组的数量
            for (int j = 0; j < l; j++) {
                if (nums[j] < nums[l]) { // 如果nums[j]小于nums[l],则可以构成一个上升三元数组
                    ans += cnt[j]; // 将以j为中心的上升三元数组数量累加到ans中
                    idx += 1; // 更新以l为右边界的上升三元数组的数量
                } else {
                    cnt[j] += idx; // 如果nums[j]大于等于nums[l],则将idx累加到cnt[j]中,表示以j为中心的上升三元数组数量增加了idx个
                }
            }
        }

        return ans; // 返回满足条件的四元组数量
    }
};

最后,感谢大神的讲解!
让我学会了一种新的思想~
(此处代码皆为模仿博主视频讲解而来)

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值