【倒推题解】三数之和及其变式的优化思路

解析美团笔试题中的数组问题,寻找符合条件的元组并统计数量。介绍了一种使用哈希表优化算法复杂度的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天美团笔试有道题是给出一个数组,找出所有 i<j<k,且符合 nums[i]-nums[j]==2*nums[j] - nums[k] 的元组,统计数量。
看完题,起手就是一个O(n^3)的遍历。
很显然,这么高复杂度肯定超时了。
考完出来看到有人的解法是:枚举i,k,同时用一个哈希表记录i到k中每个数的出现次数,如果nums[i] + nums[k]是3的倍数,答案就加上(nums[i] + nums[k]) / 3的出现次数。
妙啊,但是是怎么想出来的呢?
不妨尝试倒推一下思路。

复杂度这么高肯定是要优化。
要怎么优化呢?
很快就可以想到排个序,然后利用一些递增的特性进行剪枝。
但是无论怎么剪,都始终是O(n^3),这时候需要想怎么样才能去掉一个n
n^3来源于要枚举 i,j,k,那么就有两种方案:想办法少枚举一个变量,或者使得枚举两个变量只需要n复杂度
三数之和就是使用的就是后一种方案,结合数组升序的特性通过双指针在n复杂度内确定 j,k 的位置。
那么这题可不可以这样做呢?
把表达式整理一下就是 nums[i]+nums[k]==3 * nums[j]
问题就出在由于需要满足 i<j<k 的特性,所以上面这个式子无法结合数组升序的特性通过双指针在n复杂度内确定 j,k 的位置。
但是似乎可以通过枚举确定 j 然后结合数组升序的特性通过双指针在n复杂度内确定 i,k 的位置?
似乎是一种解法,需要多加些判断条件。
如果考虑前一种方案,就是需要一种O(1)的方案确定其中一个变量的位置,或者说,在两个变量确定的情况下通过O(1)的方式得知符合条件的元组数量。
O(1)的算法和容器都不多,要么使用公式,要么就只有哈希表了。
所以现在要尝试使用哈希表去实现在两个变量确定的情况下通过O(1)的方式得知符合条件的元组数量。
要怎么解决呢,其实很难想到,不妨先确定枚举哪两个变量。
i,j ?然后用哈希表确定 j到数组末尾的满足条件的 k ?
也就是用一个哈希表记录j到数组末尾所有数的数量,然后通过 map[ nums[i] - 3 * nums[j] ] 得到符合条件的k而组合而成的元组数量的数量
把得到的数量累加到结果集即可。
枚举 i,j 的时候让哈希表随着 j 的增大而缩小。
等下一轮 i 的时候又需要n的复杂度获得一遍map,当然,可以只算一次,然后每次都复制一份来使用。
虽然不太优雅,但是貌似也可以实现题目要求了。
按照上面思路其实可以知道,枚举任意两个变量都可以通过 map[ nums[i] - 3 * nums[j] ] 得到符合条件的元组的数量。
那么不难想到(其实挺难的),枚举 i,k 的时候,最容易维护哈希表,在枚举k的同时扩大了哈希表,枚举 i 的同时缩小了哈希表。
注意!此时不是一个滑动窗口的方法,如果是滑动窗口的话直接O(n)了,不能用滑动窗口的原因是无法利用数组升序的特性。
因此就得到了文章最上面提出的解法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值