zoukankan      html  css  js  c++  java
  • 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问题中。想对于穷举法,是一种“有计划”的搜索问题。

  • 相关阅读:
    Asp.Net 构架(Http Handler 介绍) Part.2<转>
    大数据插入<转>
    网站开发技巧参考大全<转>
    qq校友好东西
    SQL2005存储过程解密 <转>
    用Lucene.net对数据库建立索引及搜索<转>
    用SharpDevelop3调试ASP.NET的方法
    【转】卢彦的利用xml实现通用web报表打印
    张仰彪第二排序法 <转>
    依赖注入那些事儿 <转>
  • 原文地址:https://www.cnblogs.com/lichen782/p/leetcode_3Sum.html
Copyright © 2011-2022 走看看