15三数之和

自己的思路是将解的情况分类:只有三种情况 (正,0,负),(正,正,负),(负,负,正)。
将nums分为两个数组pos,保存正数;neg,保存负数。
当两个数组的长度小于nums的长度时说明存在0,这个时候利用哈希的方法可以找到第一种情况的所有解;
对于第二种情况,构建set:possum,保存两个不同正数的和,然后利用哈希的方法去neg中寻找;
第三种情况和第二种类似。
判题的时候发现这样无法处理:全0,会直接输出为空、有重复的正数或负数,会出现重复的元组。
看解析
哈希的方法是自己想复杂了,构建两轮循环确定a,b,然后哈希寻找-a-b就可以了,难点也确实就在于去重
然后是双指针的方法

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end() );
        
        for(int i = 0; i < nums.size(); ++i )
        {
            if( nums[i] > 0 )
                return res;
            //上一轮成立的解的下标是 i-1,left, right
            //, 因此如果这一轮的nums{i] 和nums[i-1]相等就要去重
            if(i > 0 && nums[i] == nums[i-1])
                continue;
			
	//这里指针的初始化也要注意,起始三元组是 最小负数(i),第二小负数(left),最大正数(right)
	//这样就保证了每次left和right的移动都有可能找到潜在的解
	//通过三个指针的移动来保证所有的三元组都能搜索到
            int left = i + 1;
            int right = nums.size() - 1;
			
            while(left < right)
            {
                if( nums[i] + nums[left] + nums[right] < 0 )//当前三元组的和偏小,需要增大负数
                    left++;
                else if ( nums[i] + nums[left] + nums[right] > 0 )//当前三元组的和偏大,需要减小正数
                    right--;
                else 
                {
                    res.push_back( vector<int> {nums[i], nums[left], nums[right]} );
			//只有等于0的解才需要去重
			//去重,当前符合要求的解是i,left,right,因此要比较下一次可能移动到的位置
                    while( left < right && nums[right-1] == nums[right] ) 
                        right--;
                    while( left < right && nums[left+1] == nums[left] ) //去重
                        left++;

                    //由于此时是一组和为0的解,因此为了寻找下一组可能的解,left和right必须都要移动
                    right--;
                    left++;
		    //只要当得到一组新的三元组,即不出现重复时,才重新开始判断
                }
            } 

        }
        return res;
    }
};
posted @ 2025-01-14 21:17  名字好难想zzz  阅读(26)  评论(0)    收藏  举报