Leetcode C++《热题 Hot 100-26》15.三数之和

Leetcode C++《热题 Hot 100-26》15.三数之和

写的代码超时了,正准备绞尽脑汁看怎么优化,突然发现怎么代码里面

  1. 题目
    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  1. 思路
  • 有两数之和的,用的暴力法遍历x,再二分查找sum-x,最终复杂度有nlogn,也可以用hashmap去找队友
  • 方案1:三数之和,暴力法nnlogn-n^3,借用hashmap找队友,复杂度会降低到n*n
    • 不重复的三元组:已有结果res,去重结果distinctRes,遍历一遍res
      • 如果和最后一个DistinctRes相同,继续遍历res元素
      • 如果不同,添加到DistinctRes
  • 方案2:排序,然后确定一个元素key,在数组剩余的里面使用夹逼法找其他两个元素(left, right),时间复杂度nn,空间复杂度nn【因为要缓存答案hh】
    • 加入答案的时候,为了避免重复,更新两端数字(left去重,right去重)
    • 寻找答案的时候,key也要去重(3个元素均去重)
    • 数字之和只会越加越大,所以用key>0也可以减去一些无谓查找
  1. 代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        if (nums.size() < 3)
            return res;
        sort(nums.begin(), nums.end());
        
        
        for(int i = 0; i < nums.size()-2; i++) {
            int left = i+1;
            int right = nums.size()-1;
            if (nums[i] > 0)
                break;
            if (i > 0 && nums[i] == nums[i-1])
                continue; //会重复,因为nums[i-1]已经找过一边了
            //cout << i << " " << nums[i] << endl;
            while(left < right) { //判断条件,区间内至少2个数hh,一个left,一个right
                //cout << left << " " << right << endl;
                int sum = nums[left] +nums[right] + nums[i];
                //cout << sum << endl;
                if (sum == 0) {
                    vector<int> oneres;
                    oneres.push_back(nums[i]);
                    oneres.push_back(nums[left]);
                    oneres.push_back(nums[right]);
                    res.push_back(oneres);
                    //left一直一样怎么办,right一直一样怎么办
                    while(left < right && nums[left] == nums[left+1]) left++;
                    while(left < right && nums[right] == nums[right-1]) right--;
                    left++;
                    right--;
                } else if (sum > 0){
                    right--;
                } else {
                    left++;
                }
            }
        }
        /* 
        //方案2:排序,以下四行思路不正确
        //然后整一个left_index,整一个right_index,然后求0-left-right= middle
        //middle有三种可能, middle_index<= left_index, 太小了,要让middle变大,所以你的right--
        //middle_index > left_index && middle_index < right_index: 
        //-可喜可贺有可能有解,有可能无解。left++, right--【你究竟应该移动那一边呢,你移动那一边都会漏掉题解??】
        //middle_index >= right_index, left--;  值太大了,所以你要把left和index的和变大,所以left++
        //一段弯路,可借鉴,做题目之前思路要严谨,不然写出来的代码bug太多鸟
        while(left < right-1 ) { //判断条件,区间内至少三个数hh
            int x = nums[left];
            int y = nums[right];
            int z = 0- x - y;
            cout << "index:" << left << " " << right  << " " << endl;
            cout <<"value:" <<  x << " " << y << " " << z << endl;
            int middle = -1;
            for (int i = left+1; i < right; i++) {
                cout << "cycle:" << i << " " << nums[i]  << " "  << z << endl; 
                if (nums[i] == z) {
                    middle = i;
                    vector<int> oneres;
                    oneres.push_back(nums[left]);
                    oneres.push_back(nums[i]);
                    oneres.push_back(nums[right]);
                    res.push_back(oneres);
                    left++;
                    //right--;
                    break;
                }
            }
            if (middle == -1) {
                //没找到答案证明有三种情况
                // left+1, right-1
                if (z <= nums[left+1]) {
                    right--;
                } else if (z >= nums[left+1] && z <= nums[right-1]) {
                    left++;
                    //right--;
                } else {
                    left++;   //你需要一个很大的数,但是你没有那个很大的数,所以你要增加left
                }
            }
        }*/

        return res;
    }
};
发布了205 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Alexia23/article/details/104170283
今日推荐