LeetCode 015 3Sum

15. 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.

Note: 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]
]
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    }
};
解题思路:
  • 自己的解题思路
一开始打算用两个指针技术,进行求解。但是遇到 下一步怎么走 问题。
最后用了一个重复查询的方法,进行搜索。
  • 别人的解题思路
别人用的两个指针技术与我的不同,他是先确定一点,然而左右搜。我的则是先确定前后两点,然后再确定一点。
学习收获:
  • 对于不重复的,可以采用 pre-check 技术,直接转到下一个不重复的值。
  • 知道 reserve() 对运行时间的影响
  • 熟悉了 unique(),resize(),distance()[ <iterator> 里面 ], 以及 erase() 操作。
  • 对于 vector erase()    只改变 size, 而且分 2 个版本: (1) 删除 1 个值  (2) 删除一个区间。
//操作1
auto   it   =   unique ( res . begin (),   res . end ());
     res . resize ( distance ( res . begin (),   it ));
    //操作2
auto   it   =   unique ( res . begin (),   res . end ());
res . erase ( it ,   res . end ());
附件:程序
1 、自己的程序:
版本 1 :运用下标,进行搜索
vector < vector < int >>   threeSum ( vector < int >&   nums )
{
     bool   myComp ( vector < int >   &   a ,   vector < int >   &   b );
     sort ( nums . begin (),   nums . end ());
     vector < int >   temp ( 3 );
     vector < vector < int >>   res ;
     auto   size   =   nums . size ();
     if ( size   >=   3 )
     {
         decltype ( size )   st   =   0 ;
         decltype ( size )   ed   =   size   -   1 ;
         while (( ed   -   st )   >=   1   &&   nums [ st ]   <=   0   &&   nums [ ed ]   >=   0 )
         {
             while (( ed   -   st )   >=   1   &&   nums [ ed ]   >=   0 )
             {
                 int   wt   =   -( nums [ st ]   +   nums [ ed ]);
                 auto   mid   =   find ( nums . begin ()   +   st   +   1 ,   nums . begin ()   +   ed ,   wt );
                 if ( mid   !=   nums . begin ()   +   ed )
                 {
                     temp [ 0 ]   =   nums [ st ];
                     temp [ 1 ]   =   * mid ;
                     temp [ 2 ]   =   nums [ ed ];
                     res . push_back ( temp );
                 }
                 -- ed ;
             }
             while (( ed   -   st )   >=   1   &&   nums [ st ]   ==   nums [ st   +   1 ])
             {
                 ++ st ;
             }
             ++ st ;
             ed   =   size   -   1 ;
         }
     }
     auto   it   =   unique ( res . begin (),   res . end ());
     res . resize ( distance ( res . begin (),   it ));
     return   res ;
}
改进版 1 :改进后的程序,不再需要 unique() 操作
vector < vector < int >>   threeSum ( vector < int >&   nums )
{
     bool   myComp ( vector < int >   &   a ,   vector < int >   &   b );
     sort ( nums . begin (),   nums . end ());
     vector < int >   temp ( 3 );
     vector < vector < int >>   res ;
     res . reserve ( 100 );
     auto   size   =   nums . size ();
     if ( size   >=   3 )
     {
         decltype ( size )   st   =   0 ;
         decltype ( size )   ed   =   size   -   1 ;
         while (( ed   -   st )   >=   1   &&   nums [ st ]   <=   0   &&   nums [ ed ]   >=   0 )
         {
             while (( ed   -   st )   >=   1   &&   nums [ ed ]   >=   0 )
             {
                 int   wt   =   -( nums [ st ]   +   nums [ ed ]);
                 auto   mid   =   find ( nums . begin ()   +   st   +   1 ,   nums . begin ()   +   ed ,   wt );
                 if ( mid   !=   nums . begin ()   +   ed )
                 {
                     temp [ 0 ]   =   nums [ st ];
                     temp [ 1 ]   =   * mid ;
                     temp [ 2 ]   =   nums [ ed ];
                     res . push_back ( temp );
                 }
                 while (( ed   -   st )   >=   1   &&   nums [ ed ]   ==   nums [ ed   -   1 ])
                 {
                     -- ed ;
                 }
                 -- ed ;
             }
             while (( ed   -   st )   >=   1   &&   nums [ st ]   ==   nums [ st   +   1 ])
             {
                 ++ st ;
             }
             ++ st ;
             ed   =   size   -   1 ;
         }
     }
     return   res ;
}
版本 2 :运用迭代器,进行搜索
vector < vector < int >>   threeSum ( vector < int >&   nums )
{
     vector < vector < int >>   res ;
     if ( nums . size ()   <   3 )
     {
         return   res ;
     }
     sort ( nums . begin (),   nums . end ());
     auto   p   =   nums . begin ();
     auto   q   =   nums . begin ()   +   1 ;
     for (;   p   <   nums . end ()   -   1 ;)
     {
         while ( q   !=   nums . end ())
         {
             int   toFind   =   -(* p   +   * q );
             auto   pos   =   find ( q   +   1 ,   nums . end (),   toFind );
             if ( pos   !=   nums . end ())
             {
                 res . push_back ({   * p ,   toFind ,   * q   });
             }
             if ( toFind   <   0 )
             {
                 break ;
             }
             else
             {
                 auto   pre_q   =   q   +   1 ;
                 while ( pre_q   !=   nums . end ()   &&   (* pre_q   ==   * q ))
                 {
                     ++ pre_q ;
                 }
                 q   =   pre_q ;
             }
         }
         auto   pre_p   =   p   +   1 ;
         while ( pre_p   <   ( nums . end ()   -   1 )   &&   (* pre_p   ==   * p ))
         {
             ++ pre_p ;
         }
         p   =   pre_p ;
         q   =   p   +   1 ;
     }
     return   res ;
}
版本 3 :使用 Two-pointer tech ,但是无法通过所有的 cases
vector < vector < int >>   threeSum ( vector < int >&   nums )
{
     vector < vector < int >>   res ;
     if ( nums . size ()   <   3 )
     {
         return   res ;
     }
     sort ( nums . begin (),   nums . end ());
     auto   p   =   nums . begin ();
     auto   q   =   nums . end ()   -   1 ;
     while ( p   <   q )
     {
         int   toFind   =   -(* p   +   * q );
         auto   pos   =   find ( p   +   1 ,   q ,   toFind );
         if ( pos   !=   q )
         {
             res . push_back ({   * p ,   toFind ,   * q   });
         }
         if ( toFind   <   0 )
         {
             auto   pre_q   =   q   -   1 ;
             while ( pre_q   !=   p   &&   (* pre_q   ==   * q ))
             {
                 -- pre_q ;
             }
             q   =   pre_q ;
         }
//对于toFind==0情况,讨论不足。
         else
         {
             auto   pre_p   =   p   +   1 ;
             while ( pre_p   !=   q   &&   (* pre_p   ==   * p ))
             {
                 ++ pre_p ;
             }
             p   =   pre_p ;
         }
     }
     return   res ;
}
错误用例

Input:[-2,0,1,1,2]

Output:[[-2,0,2]]

Expected:[[-2,0,2],[-2,1,1]]

2 、别人的程序
使用 Two-pointers tech ,可以通过。
vector < vector < int >   >   threeSum ( vector < int >   & num )
{
     vector < vector < int >   >   res ;
     std :: sort ( num . begin (),   num . end ());
     for ( int   i   =   0 ;   i   <   num . size ();   i ++)
     {
         int   target   =   - num [ i ];
         int   front   =   i   +   1 ;
         int   back   =   num . size ()   -   1 ;
         while ( front   <   back )
         {
             int   sum   =   num [ front ]   +   num [ back ];
             // Finding answer which start from number num[i]
             if ( sum   <   target )
                 front ++;
             else   if ( sum   >   target )
                 back --;
             else
             {
                 vector < int >   triplet ( 3 ,   0 );
                 triplet [ 0 ]   =   num [ i ];
                 triplet [ 1 ]   =   num [ front ];
                 triplet [ 2 ]   =   num [ back ];
                 res . push_back ( triplet );
                 // Processing duplicates of Number 2
                 // Rolling the front pointer to the next different number forwards
                 while ( front   <   back   &&   num [ front ]   ==   triplet [ 1 ])   front ++;
                 // Processing duplicates of Number 3
                 // Rolling the back pointer to the next different number backwards
                 while ( front   <   back   &&   num [ back ]   ==   triplet [ 2 ])  rear --;
             }
         }
         // Processing duplicates of Number 1
         while ( i   +   1   <   num . size ()   &&   num [ i   +   1 ]   ==   num [ i ])
             i ++;
     }
     return   res ;
}
比较简短版的
vector < vector < int >>   threeSum ( vector < int >&   nums )
{
     vector < vector < int >>   triples ;
     triples . reserve ( 200 );
     sort ( nums . begin (),   nums . end ());
     int   i   =   0 ,   last   =   nums . size ()   -   1 ;
     while ( i   <   last )
     {
         int   a   =   nums [ i ],   j   =   i   +   1 ,   k   =   last ;
         while ( j   <   k )
         {
             int   b   =   nums [ j ],   c   =   nums [ k ],   sum   =   a   +   b   +   c ;
             if ( sum   ==   0 )   triples . push_back ({   a ,   b ,   c   });
             if ( sum   <=   0 )   while ( nums [ j ]   ==   b   &&   j   <   k )   j ++;
             if ( sum   >=   0 )   while ( nums [ k ]   ==   c   &&   j   <   k )   k --;
         }
         while ( nums [ i ]   ==   a   &&   i   <   last )   i ++;
     }
     return   triples ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值