这个题目,我没有使用太多技巧,直接解决的。虽然不是很难,但是调试花了不少时间。
提炼重点信息:
1.需要非降序输出,所以处理数据之前,先排序一下,是必要的。
2.数组中三个数相加等于0的三元组,而且满足唯一性:
   假设a,b,c是满足相加等于0,而且非降序
   那么 a <= 0,a,b固定了,c就固定了。
   所以我们确定一个方案:从排序后的数组顺序取值。
   假设数组大小是n,a的位置i在0到n-3的范围,b的位置j在a的下一个位置i+1开始到n-2的范围,c的位置k在b的下一个位置j+1到n -1的位置
   处理好各种边界,重复计算的地方:
   假设a的当前位置的值a[i]等于前一个位置的值a[i-1],那么是可以直接跳过的。为啥?后面的循环是前面循环的子集。同理b也是一样的。
   另外left = -(a+b),需要在后续的最大最小值范围之内,即: left < num[j] 肯定在数组后面的值中找不到,数组排序后是非降序的。大于数组最大值,肯定也是找不到的。
   在c的位置搜索范围能找到一个c跟left相等就可以停止c的当前搜索了,a,b固定,c一定是唯一的。另外c已经比left大了,也不需要搜索了,后面的值更大。
   
   
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        int n = num.size();
        vector<vector<int> > res;
        sort(num.begin(), num.end());
       
        for(int i=0;i<n-2;i++){
            if(num[i] > 0){
                break;
            }
            
            if(i > 0 && num[i] == num[i-1]){
               continue;
            }
            
//             printf("num[%d] = %d\n",i,num[i]);
            for(int j=i+1;j<n-1;j++){
                if(j > i+1 && num[j] == num[j-1]){
                    continue;
                }
                
                int left = -(num[i] + num[j]);
                if(left < num[j]){
                    break;
                }
                
                if(left > num[n-1]){
                    continue;
                }
//                 printf("num[%d] = %d,num[%d] = %d\n",i,num[i],j,num[j]);
                for(int k=j+1;k<n;k++){
                    if(num[k] == left){
//                         printf("num[%d] = %d,num[%d] = %d,num[%d] = %d\n",i,num[i],j,num[j],k,num[k]);
                        res.push_back({num[i],num[j],num[k]});
                        break;
                    }
                    
                    if(num[k] > left){
                        break;
                    }
                }
            }
        }

        return res;
    }
};