题目要求:

java 三个同时有 或者三个同时没有_i++


分析:

这道题目最烦的一点就是要不断地进行优化。我最初写好的雏形代码是超出时间限制的,所以优化的过程也是一点一点来的。

OK,先不说优化的问题,先说一说拿到这道题目我是如何思考的。

  • 由于我们想要找到三数之和为0的三个数,并且放在集合中,脑海里首先就应该要想到:
    (1) 将nums数组进行排序,并设置left和right两个指针,分别先指向头跟尾,往中间夹击;
    (2) 结果要要放在一个集合中,并且这个集合中还有一个一个的小集合,所以需要定义两个集合:大集合用来存放所有小集合,小集合存放加起来等于0的三个数;
  • 有了1中的思路之后,代码雏形就出来了:
    (1) 我们对排序后的nums数组进行遍历,让nums[i]作为三个数中的一个;
    (2) 令left指向nums[i + 1](left的值为i + 1,指向的数字是nums[i + 1],后同),right指向排过序之后的nums数组的最后一个数字nums[length - 1];
    (3) 将这三个数进行相加,判断它们的和是否为0:
  • 如果为0,则添加到小集合中,并将这个小集合添加到大集合中;
  • 如果大于0,则将right --;
  • 如果小于0,则将left ++.
    至此,代码的雏形就完成了,接下来我们要做的事情是对这个雏形代码进行优化。
    我们可以从以下几个方面来对代码进行优化:
    (1) 当nums的长度小于3时,直接不用判断了,返回一个空的集合list即可;
    (2) 如果一个数与前面的数是相同的,如nums = [-3, -2, -2, 2, 3, 5]中,走到nums[2]时,发现nums[2]与nums[1]相等,就直接忽略它,将i++;
    (3) 同样的,在判断left和right进行移动的时候,也像3中那样去判断;
    (4) 如果说第一个数字就大于0,那么就没有找下去的必要了。

好了,经过这些分析,我们最终的代码如下所示:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        Arrays.sort(nums);
        List<Integer> list2 = null;
        if(nums.length < 3)
            return list;
        for(int i = 0; i < nums.length; i++) {
            if(i > 0 && nums[i] == nums[i-1])
                continue;
   if(nums[i] > 0) {
                break;
            }
            int left = i + 1, right = nums.length - 1;
            while(left < right) {
                int t = nums[left] + nums[right] + nums[i];
                if(t == 0) {
                    list2 = new ArrayList<Integer>();
                    list2.add(nums[i]);
                    list2.add(nums[left]);
                    list2.add(nums[right]);
                    list.add(list2);
                    while(left < right && nums[right] == nums[right - 1])
                        right --;
                    while(left < right && nums[left] == nums[left + 1])
                        left ++;
                } 
                if(t > 0) {
                    right --;
                } else {
                    left ++;
                }
            }
        }
        return list;
    }
}