N-sum问题通解

本文首发在我的个人博客:https://jlice.top/p/7qvfi/。欢迎大家前去参观,么么哒~

N-sum 问题还是比较典型的,这里进行一下小结。

首先描述一下 N-sum 问题:有一个数组 nums,要求从数组中选择 n 个数,使得这些数的和恰好为 target ,输出所有不重复的可行组合。

如果采用暴力解法,显然时间复杂度为 \(O(N^n)\),这一般是不可取的。

下面是 N-sum 问题的LeeCode链接:

1. Two Sum

15. 3Sum

18. 4Sum

Two-Sum

先来解决Two-Sum问题,这是N-sum问题的基础。如果我们能把Two-Sum的时间复杂度降为 \(O(N)\) ,然后就能把N-sum的时间复杂度降为 \(O(N^{n-1})\) 了。

如果采用暴力解法,每次选择一个数时,都要遍历数组来选择另一个数,并判断和是否为 target,这样显然是低效的。当我们选择一个数 x 时,我们希望数组里有一个数为 target - x。为了快速判断数组里是否有某个数,可以用 HashSet。但是,这样存在问题,因为数组里可能有重复的数,当 x 等于 target - x 时,这种做法就错了。因此,正确的做法应该是用 HashMap,用来存储各个数还有多少可用。

双指针法

另一种解法是使用“双指针”,这种解法要求 nums 是有序的。例如,nums 为 [1, 2, 4, 7, 13, 16],target 为 15。初始时,指针p、q位于两端:

https://jlice-top.oss-cn-beijing.aliyuncs.com/a5ae722e0d7c11e9ae48509a4c21c90b.png

如果p、q所指向的值之和大于 target,那么q往左移,这是因为q左侧的值比q所指的值小,所以q往左移能使得之和变小; 如果之和小于 target,那么p往右移,这是因为p右侧的值比p所指的值大,所以p往右移能使得之和变大; 如果之和等于 target,那么p往右移且q往左移(有点像夹挤),这个稍微有点难理解,这也是“双指针”法的思想精髓。首先,如果p往左移或q往右移,其实就回到了之前的状态;其次,如果只是p往右移,显然之和会大于 target,如果只是q往左移,显然之和会小于 target;于是乎,p往右移且q往左移。

https://jlice-top.oss-cn-beijing.aliyuncs.com/3f87a4d80d9711e9b32b509a4c21c90b.png

然后就是考虑如何判断可行组合是否重复。由于数组是有序的,可行组合的加入也是有序的,因此,只需判断当前可行组合与最后一个已加入的可行组合是否重复即可。

代码

vector<vector<int>> twoSum
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值