zoukankan      html  css  js  c++  java
  • 【LeetCode-数组】三数之和

    题目描述

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
    注意:答案中不可以包含重复的三元组。
    示例:

    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    

    题目链接:https://leetcode-cn.com/problems/3sum/

    思路1

    比较基础的方法,先找到两个数,然后固定住这两个数去寻找满足条件的第三个数,为了加快寻找速度可以通过哈希表来寻找。代码如下:

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int>> ans;
            if(nums.empty())
                return ans;
    
            map<int, int> hashTabel;
            for(int i=0; i<nums.size(); i++)
                hashTabel[nums[i]] = i;
            
            for(int i=0; i<nums.size(); i++){
                for(int j=i; j<nums.size(); j++){
                    int complement = -nums[i]-nums[j];
                    if(i!=j && hashTabel.find(complement)!=hashTabel.end() 
                    && hashTabel[complement]!=i && hashTabel[complement]!=j){
                        ans.push_back({nums[i], nums[j], nums[hashTabel[complement]]});
                    }
                }
            }
            // 使用set去重
            for(int i=0; i<ans.size(); i++)
                sort(ans[i].begin(), ans[i].end());
            set<vector<int>> s(ans.begin(), ans.end());
            ans.assign(s.begin(), s.end());
    
            return ans;
        }
    };
    // 超时
    

    这样的话得到的结果里面包含重复的三元组,所以使用set去重后返回。

    • 时间复杂度O(n^2)
      包含一个双层循环。
    • 空间复杂度O(n)
      使用了哈希表。

    该方法由于超时未通过。

    思路2

    假如是在排序数组中找和为target的两个数,则我们可以使用两个指针,一个指针left从左到右遍历,另一个指针right从右到左遍历。如果两个指针指向的两个数字之和小于target,则left++;如果大于target,则right--。直至找到target或者left>=right。代码如下:

    //array = [1,2,3,4,5,6,7,8,9]; array is sorted in a increasing order
    //target = 10;
    int len = array.size();
    int p1 = 0, p2 = len - 1; //p1 points to the start of the array and p2 points to the end
    //the search stops when the two pointers meet each other
    while(p1 < p2){
        if(array[p1] + array[p2] < target){
            p1++;
        }else if(array[p1] + array[p2] == target){
            cout << p1 << p2 << endl;
            p1++,p2--;
        }else{
            p2--;
        }
    
    }
    

    对于这个问题,我们可以用类似的思想。首先,将数组排序,然后从头开始遍历数组,当遍历到nums[i]时,我们从i+1开始往后利用上面的方法寻找两个值使得两个值之和为-nums[i]即可。
    还有一个问题就是去重,例如输入为[-1,-1,0,0,1,1],算法结果中会包含两个[-1,0,1]。解决这个问题的办法是:当移动指针的时候,要移动到一个位置,这个位置和指针移动前指向的值不同,而不是简单地将指针移动一步。代码如下:

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int>> ans;
            if(nums.empty() || nums.size()<3)
                return ans;
    
            sort(nums.begin(), nums.end());
    
            for(int i=0; i<nums.size(); i++){
                if(i==0 || (i>0&&nums[i]!=nums[i-1])){
                    int left = i+1;
                    int right = nums.size()-1;
                    while(left<right){
                        int s = nums[i]+nums[left]+nums[right];
                        if(s<0){
                            left++;
                        }else if(s>0) {
                            right--;
                        }else{
                            ans.push_back({nums[i], nums[left], nums[right]});
                            while(left<right && nums[left]==nums[left+1]){  // 找到下一个不相等的下标,为了去重
                                left++;
                            }
                            while(left<right && nums[right]==nums[right-1]){ // 找到下一个不相等的下标,为了去重
                                right--;
                            }
                            left++;
                            right--;
                        }
                    }
                }
            }
            return ans;
        }
    };
    
    • 时间复杂度O(n^2)
    • 空间复杂度O(n)

    总结

    双指针的应用场景:去重、找满足条件的数字、链表相关问题等。

    参考

    1、https://leetcode-cn.com/problems/3sum/solution/xiang-xi-jie-shi-shuang-zhi-zhen-jie-jue-san-shu-z/
    2、https://leetcode-cn.com/problems/3sum/solution/pai-xu-shuang-zhi-zhen-zhu-xing-jie-shi-python3-by/

  • 相关阅读:
    请问发表的文章如何备份?
    .NET中利用XML来自动生成代码策略
    XPO使用随笔
    为方便做封包分析,做了个十六进制和字符互转的网页小工具
    前端人员如何模拟慢网速环境
    补充《动态加载外部.js文件时候,javascript的执行顺序问题》
    凡客诚品官方网站的前端改进建议
    "Cachecontrol”常见的取值private、nocache、maxage、mustrevalidate及其用意
    javascript跨域操作cookie的点滴记录
    HTTPS的七个误解(译文转载)
  • 原文地址:https://www.cnblogs.com/flix/p/12651825.html
Copyright © 2011-2022 走看看