zoukankan      html  css  js  c++  java
  • 3Sum

    1. Question

    给一个整型数组,找所有唯一的和为0的三个数的数对。相似的题有2Sum

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
    
    Note:
    Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
    The solution set must not contain duplicate triplets.
        For example, given array S = {-1 0 1 2 -1 -4},
    
        A solution set is:
        (-1, 0, 1)
        (-1, -1, 2)

    2. Solution

    需要考虑的特殊情况:

    • 数组元素个数<3
    • 重复数对

    2.1 O(n3)

    遍历所有的三个数组成的数对,找到符合要求的。

    分析:遍历过程中有很多数对是可以忽略考虑的,例如考察a、b时,如果目前发现a+b+c>0,则所有比c大的数其实都不必考虑。同理a+b+c<0时,所有比c小的数都不用再考虑。

    2.2 O(n2)

    2.2.1 利用2SUM(双指针)

    首先对数组按升序排序,依次假设前n-2个数是符合要求的数对中的一员,对比该数大的数,采用2SUM方法找符合要求的剩余两数。

     1 public class Solution {
     2     //O(n2)
     3     public List< List< Integer > > threeSum( int[] num ){
     4         int len = num.length;
     5         ArrayList< List< Integer> > res = new ArrayList<List<Integer>>();
     6         if( len<3 )
     7             return res;
     8         Arrays.sort( num );
     9         
    10         if( num[0]>0 || num[len-1]<0 )
    11             return res;
    12         
    13         HashSet< List<Integer> > test = new HashSet< List< Integer> >();
    14         for( int i=0; i<len-2 && num[i]<=0; i++ ){
    15             //based on twoSum, use two pointer
    16             for( int j=i+1, k=len-1; j<k; ){
    17                 int now = num[i] + num[j] + num[k];
    18                 if( now==0 ){
    19                     ArrayList< Integer> aTriple = new ArrayList< Integer >();
    20                     aTriple.add( num[i]);
    21                     aTriple.add( num[j]);
    22                     aTriple.add( num[k]);
    23                     if( test.add( aTriple ))
    24                         res.add( aTriple );
    25                     j++;
    26                     k--;
    27                 }
    28                 else if( now<0 )
    29                     j++;
    30                 else
    31                     k--;
    32             }
    33         }
    34         
    35         return res;        
    36     }
    37 }
    View Code

    2.2.2 利用2SUM(map)

    map可以不用排序,同时实现找的时间为常数时间。是最符合人思维的方式。

    public class Solution {
        private void addToRes( List<List<Integer>> res, int i, int j, int k ){
            ArrayList< Integer > aTriple = new ArrayList< Integer >();
            aTriple.add( i );
            aTriple.add( j );
            aTriple.add( k );
            res.add(aTriple);
        }
        
        //o(n2)
        public List< List< Integer> > threeSum( int[] num ){
            ArrayList< List< Integer> > res = new ArrayList<List< Integer> >();
            if( num.length < 3 )
                return res;
            Arrays.sort( num );
            int len = num.length;
            if( num[len-1] < 0 || num[0] > 0 )
                return res;
            if( (num[0]==0 && num[2]==0 ) || ( num[len-1]==0 && num[len-3] ==0 ) ){
                addToRes( res, 0, 0, 0 );
                return res;
            }
            HashMap<Integer, Integer> sortNum = new HashMap< Integer, Integer >();
            int count = 0;
            int i=0;
            while( i < len ){
                if( sortNum.containsValue( num[i]) ){
                    if( i<len-1 &&  num[i] == 0 && num[i+1] == 0 )
                        addToRes( res, 0, 0, 0 );
                    else{
                        if( num[i]!=0 && Arrays.binarySearch( num, -2 * num[i] ) >=0 ){
                            if( num[i] < 0 )
                                addToRes( res, num[i], num[i], -2 * num[i] );
                            else
                                addToRes( res, -2*num[i], num[i], num[i] );
                        }                    
                    }
                    while( ++i<len && num[i] == num[i-1] );
                }
                else{
                    sortNum.put( count++, num[i] );
                    for( int j=0; j<count-1; j++ ){
                        int vj = sortNum.get(j);
                        int vk = -1 * ( num[i] + vj );
                        if( vj < vk && vk != num[i]  && sortNum.containsValue( vk )  )
                            addToRes( res, vj, vk, num[i] );
                    }
                    i++;
                }
            }
            return res;
        }
    }
    View Code
  • 相关阅读:
    技术必备:推荐一款接口自动化测试数据校验神器
    提高GUI自动化测试稳定性解决方案
    新特性,推荐一款超强接口管理神器 Apifox
    测试开发:从0到1学习如何测试API网关
    接口自动化测试,一键快速校验接口返回值全部字段
    测试工程师必学:测试人员如何深入了解项目
    Django+Vue+Docker搭建接口测试平台实战
    如何开展线上全链路压测思路分享
    刚转行1年测试新手:学习Python编程经验实战分享
    测开新手:从0到1,自动化测试接入Jenkins学习
  • 原文地址:https://www.cnblogs.com/hf-cherish/p/4596534.html
Copyright © 2011-2022 走看看