最近在刷 LeetCode 上的题为找工作提前做准备,在刷 Array 类问题的 Easy 难度的题的时候觉得还好,大部分的题还是能够想得出来,但是在刷到 Medium 难度的时候,明显感觉难度提升了,其中有一类题型连续出现引起了我的注意,就是 K Sum 问题。
K Sum问题就是,给出一个数作为 target,和一个数组作为待查数组,在这个待查数组里找出 K 个数之和等于 target.
最简单的 2 Sum
2 Sum应该是最简单的了,但是它是解决我们后面 3 Sum和 4 Sum 问题的最小子问题了。如果一开始就用暴力循环的方法当然是做的出来,但是,一是 LeetCode 可能会判超时(在 3 Sum 和 4 Sum 问题中确实会超时) ,二是暴力穷举也没什么意思。最简单的穷举法是 O(n^2) 的时间复杂度,那么我们可以将数组排好序后,用头尾两个指针一次迭代即可找出,时间复杂度降为了 O(nlogn).
3 Sum 问题
接下来就是3 Sum问题了,用暴力法 LeetCode 已经给出了超时的提醒了,所以O(n^3)的时间复杂度肯定是不能接受的,那么我们可以想像如何分解问题,毕竟3 Sum=2 Sum + 1 Sum,那么我们完全可以用将上面 2 Sum 问题的解法嵌入到一层循环中,也就是先排序然后一个指针从头开始循环,在数组的其他数中找出 2个数的和加上这个指针指向的数的和等于 target就行了,也就是说我们已经有了循环指针指向的这个数 V,那么我们只需要在其他书中找出 num1+num2=target-V就行了,这就又把问题带回到了2 Sum上,中不过多了一层循环,时间复杂度就降为了 O(n^2)。
代码实例:
1 | /*注题目 |
3Sum Closest 问题
3Sum Closest 问题是3 Sum 问题的一个变种,意思就是给出一个 target,找出数组中最接近 target的 3 个数之和。这道题和 3 Sum 很像,不同的是需要用一个临时变量来保存当前最接近 target 的值,值得注意的是我们需要求 3个数的和减去 target 的差的绝对值来求最接近 target 的数。
1 | /* |
4 Sum 问题
4 Sum问题也显而易见了,就是求 4 个数的和等于target,那么我们可以如法炮制,前面的3 Sum我们是固定一个数,然后求两个数的和,将其分解为 2 Sum + 1 Sum,呢么 4 Sum 我们可以同样的先固定两个数,与另外两个活动的数相加等于target,也就输 4 Sum=3 Sum+1Sum。再在3 Sum的基础上嵌套一层循环就可以达到目的了,时间复杂度也降低为了O(n^3)。
1 | /* |
总结
做了 30 多到题,发现一个规律,如果排序后不使用二分查找或者双指针利用排序特性的话,那么排序书没有意义的,同时利用 Hash 特性也可以在增大空间复杂的同时减小时间复杂度。