• LeetCode 笔记系列三 3Sum


    题目Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

    For example, given array S = {-1 0 1 2 -1 -4},
    
        A solution set is:
        (-1, 0, 1)
        (-1, -1, 2)

    额外的要求是不能返回重复的triplets,返回的a,b,c的顺序要是非递减的。

    解法一:首先想一下,三个数相加,要为0的话,如果不是都为0,那么至少有一个正数一个负数。可以从这一点出发,设置两个指针i和j,分别指向数组S的首尾,always保持numbers[i] <= 0 and numbers[j]>0。哦,对了,数组要先给它排序。然后判断numbers[i] + numbers[j]的符号,如果是大于0,我们就去数组负数部分search,反之去正数部分找。因为数组是sorted,search部分可以用binarySearch。代码如下:

     1 //Program Runtime: 784 milli secs
     2     public static ArrayList<ArrayList<Integer>> threeSum(int[] num) {
     3         // Start typing your Java solution below
     4         // DO NOT write main() function
     5         Arrays.sort(num);
     6         int i = 0;
     7         int j = num.length - 1;
     8         int firstNonNegativeIndex = -1;
     9         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    10         if(j < 0 || num[i] > 0 || num[j] < 0) return result;//1.边界条件判断,如果没有非负数或者都是正数,返回空集合
    11         for(int k = 0; k < num.length;k++){
    12             if(num[k] >= 0){
    13                 firstNonNegativeIndex = k;
    14                 break;
    15             }
    16         }
    17         for(i = 0;i <= firstNonNegativeIndex;i++){
    18             if(i > 0 && num[i] == num[i-1])continue;
    19             for(j = num.length - 1; j> i + 1;j--) {
    20                 if(j <= num.length - 2 && num[j + 1] == num[j]) continue;
    21                 int twoSum = num[i] + num[j];
    22                 if(twoSum > 0) {
    23                     int searchIdx = binarySearch(num, i+1,firstNonNegativeIndex - 1, -twoSum);
    24                     if(searchIdx != -1){
    25                         addTuple(result,new int[]{num[i],num[searchIdx],num[j]});
    26                     }
    27                 }else{
    28                     int searchIdx = binarySearch(num, firstNonNegativeIndex,j-1, -twoSum);
    29                     if(searchIdx != -1){
    30                         addTuple(result,new int[]{num[i],num[searchIdx],num[j]});
    31                     }
    32                 }
    33             }
    34         }
    35         return result;
    36     }
    O(n^2logn)

    这里要注意一些边界条件的判断。

    1.如果是空数组,或者均是整数或均是负数,返回空集合;

    2.在遍历i和j的时候,为满足题设“不能返回重复的triplets”,遇到和前一个相同的i或者后一个相同的j,continue。

    虽然能通过大集合,但该解法并不是最好的。

    解法二这里提到一个O(n2)的解法。首先(当然最首先的还是要排序数组),固定i(for i from 0 to last)。对每个i,有j=i+1,k=last。对三者取和,如果大于0,说明k的那边取大了,k向前移动;如果小于0呢,说明j取得太小了,向后移动。如果等于0,记录i,j,k并同时移动j和k。

     1 public static ArrayList<ArrayList<Integer>> threeSum2(int[] num) {
     2         Arrays.sort(num);
     3         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
     4         for(int i = 0; i < num.length - 2;i++){
     5             if(i > 0 && num[i] == num[i-1])continue;
     6             int j = i + 1;
     7             int k = num.length - 1;
     8             while(j < k){
     9                 int twoSum = num[i] + num[j];
    10                 if(twoSum + num[k] > 0){
    11                     k--;
    12                 }else if(twoSum + num[k] < 0){
    13                     j++;
    14                 }else {
    15                     addTuple(result,new int[]{num[i],num[j],num[k]});
    16                     j++;
    17                     k--;
    18                     while(num[j] == num[j - 1] && num[k]==num[k+1] && j < k){
    19                         j++;
    20                         k--;
    21                     }
    22                 }
    23             }
    24         }
    25         return result;
    26     }
    O(n^2)

    这道虽然不是那么难,但是要注意的是边界条件的判断和代码的简洁;排序是个好东西。

    解法二这种,还可以应用到4Sum,3SumCloset问题中。想对于穷举法,是一种“有计划”的搜索问题。

  • 相关阅读:
    [转]在WEB下的客户端控件的开发应用
    [转]C#将文件保存到数据库中或者从数据库中读取文件
    [转]如何组织一个高效的开发团队
    [转]使用C#调用金诚信71x系列读卡器的DLL
    [转]统一建模语言UML轻松入门之综合实例
    [转]Web application 的压力测试 MS Web Application Stress Tool (was)
    [转]使用NUnit在.Net编程中进行单元测试
    国外著名人脸识别介绍文章
    js与as通信
    php访问mysql 封装
  • 原文地址:https://www.cnblogs.com/lichen782/p/leetcode_3Sum.html
Copyright © 2020-2023  润新知