• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
reLeetCode 热题 100- 15. 三数之和

1 排序

2 双指针 位置卡死逐步对着移动 左右2个指针

3 while 跳过重复的数

image

 双指针

class Solution {
public:

    vector<vector<int>> my_test1(vector<int>& nums) {
        std::set<int> index_set;
        std::map<std::set<int>,vector<int>> result_map;
        vector<vector<int>> result_vector;
        //sort(nums.begin(),nums.end());
        //std::cout<< nums << std::endl;
        for(int i=0;i<nums.size()-2;i++){
            
            for(int j=i+1;j<nums.size()-1;j++){ 

   

                  for(int z=j+1;z<nums.size();z++){
                    int all_=nums[i]+nums[j]+nums[z];
                    if(all_==0){
                        // index_set.insert(nums[i]);
                        // index_set.insert(nums[j]);
                        // index_set.insert(nums[z]);
                        result_map.insert({{nums[i],nums[j],nums[z]},{nums[i],nums[j],nums[z]}});
                        break;
                        
                    } 
                  }


            }


        }

        for (auto &it : result_map){

            result_vector.push_back(it.second);

        }
        return result_vector;
    }
  
    vector<vector<int>> my_test2(vector<int>& nums) {
        std::set<int> index_set;
        std::map<std::set<int>,vector<int>> result_map;
        vector<vector<int>> result_vector;

        unordered_multiset<int> sourc_udset(nums.begin(), nums.end());
       
        //sort(nums.begin(),nums.end());
        std::cout<< nums.size() << std::endl;
        for(int i=0;i<nums.size()-2;i++){
            
            for(int j=i+1;j<nums.size()-1;j++){ 

                int target=0-nums[i]-nums[j];
             
                auto range = sourc_udset.equal_range(target);
                size_t count = std::distance(range.first, range.second);
                
                
                if(target==nums[i] && target==nums[j] ){    
                    if (count >= 3) {
                        result_map.insert({{nums[i],nums[j],target},{nums[i],nums[j],target}});
                        //auto second = std::next(range.first);
                        // 安全访问第二个
                    } else {
                        std::cout << "没有第二个匹配元素" << std::endl;
                    }
                }
                else if(target==nums[i] || target==nums[j] ){

                    if (count >= 2) {
                         result_map.insert({{nums[i],nums[j],target},{nums[i],nums[j],target}});
                        }

                }
                else{
                    if (count >=1) {
                        result_map.insert({{nums[i],nums[j],target},{nums[i],nums[j],target}});
                    }
                }

                    
            }


        }

        for (auto &it : result_map){

            result_vector.push_back(it.second);

        }
        return result_vector;
    }

       vector<vector<int>> my_test3(vector<int>& nums) {
        std::set<int> index_set;
        std::map<std::set<int>,vector<int>> result_map;
        vector<vector<int>> result_vector;

        unordered_multiset<int> sourc_udset(nums.begin(), nums.end());
       
        sort(nums.begin(),nums.end());// 先排序
        std::cout<< nums.size() << std::endl;
        bool stop=0;
        int lastZ=nums.size()-1;
        for(int i=0;i<nums.size()-2;i++){
            if(nums[i]>0) return result_vector; // 排序前提下 第一个数大于0,直接挂
            
            for(int j=i+1;j<nums.size()-1;j++){ 

                if((nums[i]+nums[j])>0) {return result_vector;}// 排序前提下 第一个数+第二个数 大于0,直接挂



                for(int z=lastZ;z>j;z--){ 

                    
                    int temp_=nums[i]+nums[j]+nums[z];
                    
                    if(temp_==0){
                          result_map.insert({{nums[i],nums[j],nums[z]},{nums[i],nums[j],nums[z]}});
                          stop=1;
                          lastZ=z;
                          break; 
                    }
                    else if(temp_<0){// 排序前提下 这个j小不行j++ z已经最大
                          lastZ=z;
                        break; 
                    }
                    else{// 大于0 排序前提下 必然在 j-z之间 z是最大的往下降 z--
                          lastZ=z;

                    }


                }

                if(stop)
                {   
                    stop=0;
                    break;
                }
            }

              


        }

        for (auto &it : result_map){

            result_vector.push_back(it.second);

        }
        return result_vector;
    }

    vector<vector<int>> my_test4(vector<int>& nums) {
       // std::set<int> index_set;
        std::map<std::set<int>,vector<int>> result_map;
        vector<vector<int>> result_vector;

       // unordered_multiset<int> sourc_udset(nums.begin(), nums.end());
       
        sort(nums.begin(),nums.end());// 先排序
        std::cout<< nums.size() << std::endl;

        for(int i=0;i<nums.size()-2;i++){
            if(nums[i]>0) {
               break; // 排序前提下 第一个数大于0,直接挂
            }

            int qian=i+1;
            int hou=nums.size()-1;

            while(qian<hou){

               int temp2= nums[qian]+nums[i];
               if(temp2>0){
                break;
               }

               while(qian<hou){
                    //cout<< i << " / " << nums[i] << " " << qian << " / " << nums[qian]  <<  "  " << hou<< "  / " << nums[hou] <<endl;
                    int temp3= nums[qian]+nums[i]+nums[hou];
                    if(temp3>0){
                        hou--;
                        while(nums[hou]==nums[hou+1] && hou>qian){
                            hou--;
                        }
                    }
                    else if(temp3==0){
                      //  cout<< " 成功 "<< i << " / " << nums[i] << " " << qian << " / " << nums[qian]  <<  "  " << hou<< "  / " << nums[hou] <<endl;
                        //result_map.insert({{nums[i],nums[qian],nums[hou]},{nums[i],nums[qian],nums[hou]}});
                        result_vector.push_back({nums[i],nums[qian],nums[hou]});
                        
                        qian++;
                        while(nums[qian]==nums[qian-1] && qian<hou){
                            qian++;
                        }
                                   
                        while(nums[i]==nums[i+1] && i<nums.size()-2 ){
                            i++;
                        }
        

                        break;
                    }
                    else{
                        qian++;
                        while(nums[qian]==nums[qian-1]&& qian<hou){
                            qian++;
                        }
                    }
                    //if(nums[hou]==nums[hou-1] && qian<(hou-1))hou--; 
               }

              



            }





        }
           

        for (auto &it : result_map){

            //cout<< " 加入"<<endl;

            result_vector.push_back(it.second);

        }
        return result_vector;
    }


    vector<vector<int>> threeSum(vector<int>& nums) {
        
      
    
       // return my_test1(nums);

        return my_test4(nums);
        
    }
};

  

 

参考答案

官方

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        // 枚举 a
        for (int first = 0; first < n; ++first) {
            // 需要和上一次枚举的数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            // c 对应的指针初始指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举 b
            for (int second = first + 1; second < n; ++second) {
                // 需要和上一次枚举的数不相同
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                // 需要保证 b 的指针在 c 的指针的左侧
                while (second < third && nums[second] + nums[third] > target) {
                    --third;
                }
                // 如果指针重合,随着 b 后续的增加
                // 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
                if (second == third) {
                    break;
                }
                if (nums[second] + nums[third] == target) {
                    ans.push_back({nums[first], nums[second], nums[third]});
                }
            }
        }
        return ans;
    }
};

作者:力扣官方题解
链接:https://leetcode.cn/problems/3sum/solutions/284681/san-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  网友

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums); // 先排序
        List<List<Integer>> res = new ArrayList<>();
        
        for (int i = 0; i < nums.length; i++) {
            // 跳过重复元素
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // 双指针,目标是找到 nums[l] + nums[r] = -nums[i]
            int l = i + 1, r = nums.length - 1;
            int target = -nums[i];
            
            while (l < r) {
                int sum = nums[l] + nums[r];
                if (sum == target) {
                    res.add(Arrays.asList(nums[i], nums[l], nums[r]));
                    l++;
                    r--;
                    // 跳过重复元素
                    while (l < r && nums[l] == nums[l - 1]) l++;
                    while (l < r && nums[r] == nums[r + 1]) r--;
                } else if (sum < target) {
                    l++;
                } else {
                    r--;
                }
            }
        }
        
        return res;
    }
}

  

 

posted on 2025-09-20 02:01  MKT-porter  阅读(3)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3