[Leetcode] 259. 3Sum Smaller

这一题和3 sum有类似又有不同之处。
3 sum有两种做法,都是O(n^2)的。一个是基于哈希表的,一个是基于排序的,两种都是2 sum O(n)做法的延伸。
这一题可以利用到的是基于排序的做法。毕竟存在大小于关系,哈希表的就没门儿了。
这题得亏不是求解集的,否则O(n^2)是没戏的,因为解集数目最大的可能性是O(n^3)个。所以一个个求出来是不现实的。
在3 sum里,基于排序的做法是先排序,然后再用target减去遍历过去的数字的同时做2 sum。
这里也是这样的,外层的for循环遍历是O(n),所以要O(n ^ 2),其实要求的是在一个排好序的数组里,用O(n)的方式做2 sum smaller。
先举一个极端的例子[1,2,3,4,5],如果target = 2,很明显,解集的数目就不是O(n)级别的。所以光用头尾像2 sum那样往前具体扫是不可以的。
再举个正常一点的例子,[1, 2, 3, 4, 5, 6, 7 ,8 ,9], 如果target = 8。
我们先用2 sum的概念走一下:

1. 1 + 9 , 1 + 8, 1 + 7都是 >=8 的,所以还往前走,右指针到了6这里,出现了第一个小于8的数字:7
这个时候有趣的现象出现了:其实除了6,1和6之间的所有数字和1相加肯定都是小于8的,因为数组是排好序的。所以这个时候我们就有了以1为左指针的解集数量了,就是6 - 1 = 5。

2. 这个时候左指针该像2 sum一样往前动了,左指针此时到了2,2 + 6 = 8,所以右指针该动了,右指针前移到5。同理,2 和 5之间的所有数字(包括5)和2相加都肯定是小于8的。所以以2为左指针的解集数量就是5 - 2 = 3

3. 左指针到3,右指针会到4。 解集数量为4 - 3 = 1

4. 左指针再尝试右移,和右指针重合,至此解答完毕。

最后,[1, 2, 3, 4, 5, 6, 7 ,8 ,9]的 2 sum smaller 得到的解集数量就是8 + 5 + 1 = 14

再像3 sum套用 2 sum一样将3 sum smaller 套用 2 sum smaller即可。给出代码如下:

    public int threeSumSmaller(int[] nums, int target) {
        int resultCnt = 0;
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            int subTarget = target - nums[i];
            int head = i + 1, tail = nums.length - 1;
            while (head < tail) {
                if (nums[head] + nums[tail] < subTarget) {
                    resultCnt += tail - head;
                    head++;
                } else {
                    tail--;
                }
            }
        }
        
        return resultCnt;
    }

猜你喜欢

转载自blog.csdn.net/chaochen1407/article/details/81303156
今日推荐