【力扣时间】【1995】【简单】统计特殊四元组

今天的简单题花样很多,值得瞅瞅

1、看题

这儿

题目很简单,解决方案也很好想。
而且,从最朴素的到复杂的思路因有尽有。

2、审题

额……
唯一需要注意的大概只有:初始数组nums[]是无序。
而由于四元组有下标大小的限制,所以不能使用排序。

当然也无需使用排序就是了。

3、思路

好了,由于题目规定4 <= nums.length <= 50,所以最无脑最暴力的四重循环在这题是可用的。
不然怎么叫简单嘛

不过当然,就算是我也不屑于就这么使用暴力解法。
所以我选择换个法子用暴力。

由于题目规定了四个数的下标必须满足a < b < c < d,所以很明显,各个指针之间有很严格的边界限制。

再加上规定nums[a] + nums[b] + nums[c] == nums[d],所以当d确定后,题目就变成了在nums[0~d]中选取三个数,来保证nums[a] + nums[b] + nums[c] == nums[d]
然后进一步,当我们在nums[0~d]中确定了c后,题目就变成了在nums[0~c]中选取两个数,来保证nums[a] + nums[b] == nums[d] - nums[c]

以此类推,思路就成形了。

4、开工

public int countQuadruplets(int[] nums) {
        int count = 0;
        for (int i = 3; i < nums.length; i++) {
            //查询剩余0~i-1范围中能否有3个数相加,结果为nums[i]
            count += find(nums, i - 1, nums[i], 2);
        }

        return count;
    }

    public int find(int[] nums, int end, int target, int deep) {
        int count = 0;
        for (int i = end; i >= deep; i--) {
            if (deep > 0) {
                //当深度不为0时,减去当前数字,并在剩余数组中继续查询
                if (nums[i] >= target) {
                    continue;
                }

                //查询子数组中,满足情况的数量
                count += find(nums, i - 1, target - nums[i], deep - 1);
            } else {
                //当深度为0时,完全匹配target
                if (nums[i] == target) {
                    count++;
                }
            }
        }

        return count;
    }

整体就是如此,在首先确认了d后,再在剩余的空间中递归确认满足条件的a、b、c的数量即可。

5、解读

整体实现和思路描述的一致。
find()方法中,我使用了deep来控制递归深度。
同时,由于我们明确知道要选取的数字的数量,便也知道了各个数字的左边界(如d>=3、c>=2这样),所以,我也用deep来控制了各个数字的左边界,而右边界自然是由上一个选择的数字决定的。

整个实现没有什么难点,所以不过多解释。

还有更好的解法,大家多动脑想想那些吧

6、提交

在这里插入图片描述
比预期的要好,毕竟还是递归的思路,本以为并不会快多少。

时间复杂度不会算。。。

7、来学大佬们的吧

大牛们的解法真的是百花齐放百家争鸣

挑几个有代表性的吧。

首先还是官解
官解提供了三种解法,从最朴实无华的暴力循环,到依赖哈希表的优化循环。
可以说,每一种都是在前一种解法的接触上升级的,而效果也越发明显。时间复杂度从O(N4)提升到了O(N2)

之后是一种多维背包解法,看了很多大佬的,但个人觉得最详细的还是三叶大佬的

8、总结

想不到简单题也能被各位大佬玩出花来。
今天也可以说是收获颇丰啊。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值