力扣hot6---双指针

题目:

TLE做法(哈希+两重for循环)

标签虽然说是用双指针,但是第一个想法真就不是双指针呀。。。就感觉这道题很像:

力扣hot1--哈希-CSDN博客

于是就用了类似的想法:

  1. 首先要排个序,至于为什么要排序,是为了好对三元组集合去重。
  2. 接下来与力扣hot1的想法一样,用哈希来存储一遍这些元素,但是有的元素可能重复了好多次(注意这里数组已经排过序了),所以unordered_map<int,vector<int>>,vector<int>记录对应的索引。
  3. 用双重for循环来判断,第三个数是否在哈希表中,如果存在,还要判断索引是不是一致,如果一致,那就还是不行。如果不一致,那就记录下来,存入res。为了方便去重,这里采用了顺序存取三个数。
  4. 最后用set去重啦,虽然TLE了,但是。。。记录一下代码(以下是TLE的代码

代码:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //nums排序
        sort(nums.begin(),nums.end());
        //哈希存
        vector<vector<int>> res;
        unordered_map<int,vector<int>> hmap;
        int len=nums.size();
        for(int i=0;i<len;i++){
            hmap[nums[i]].push_back(i);
        }
        //两重for循环遍历
        for(int i=0;i<len-1;i++){
            for(int j=i+1;j<len;j++){
                //cout<<"i:"<<i<<' '<<"j:"<<j<<endl;
                //cout<<"nums_i:"<<nums[i]<<' '<<"nums_j:"<<nums[j]<<endl;
                auto iter=hmap.find(0-nums[i]-nums[j]);
                if(iter!=hmap.end()){
                    auto p=iter->second;
                    int p_len=p.size();
                    for(int k=0;k<p_len;k++){
                        if(p[k]!=i && p[k]!=j){
                            int temp=iter->first;
                            //cout<<"i:"<<nums[i]<<" j:"<<nums[j]<<" temp:"<<temp<<endl;
                            if(temp<=nums[i]){res.push_back({temp,nums[i],nums[j]});}
                            else if(temp>=nums[j]){res.push_back({nums[i],nums[j],temp});}
                            else{res.push_back({nums[i],temp,nums[j]});}
                            break;
                        }
                    }
                }
            }
        }
        //set去重
        set<vector<int>> q(res.begin(),res.end());
        res.assign(q.begin(),q.end());

        return res;
    }
};

这里记录一下set去重:

//set去重
set<vector<int>> q(res.begin(),res.end());
res.assign(q.begin(),q.end());

C++ 给vector去重的三种方法_c++ vector去重-CSDN博客

单循环+双指针做法

言归正传,双指针思路:

  1. 首先,先给数组排个序。为什么要排序呢,有点像二分的思想。这里可以先大致感受一下,L 指针在最左面,R 指针在最右面,满足三个数之和等于0,那就添加结果。小于0就说明 L 指针指的数有点小了,往右侧移动。大于0就说明 R 指针指的数有点大了,往左侧移动。
  2. 排完序后,依次遍历数组中的每个元素,就代表三个元素之和已经降维成了两个元素之和,或许可以想到哈希表的做法(为什么双指针也很方便呢?因为这道题不是返回索引,可以进行排序),后面将尝试哈希表的做法~
  3. 如果说遍历到的元素索引为 i ,那么 L = i +1,R = nums.size( ) - 1。然后进行第一段的说法,也就是:
while(L<len && R>=0 && L<R){
    if(nums[i]+nums[L]+nums[R]==0){
        res.push_back({nums[i],nums[L],nums[R]});
        while(L<R && nums[L+1]==nums[L] && L+1<len){L++;}
        while(L<R && nums[R-1]==nums[R] && R-1>=0){R--;}
            L++;R--;
    }
    else if(nums[i]+nums[L]+nums[R]<0){L++;}
    else{R--;}
}

代码如下:

C++:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        
        sort(nums.begin(),nums.end());
        
        vector<vector<int>> res;
        int len=nums.size();
        for(int i=0;i<len;i++){
            if(nums[i]>0){break;}
            if(i>0 && nums[i]==nums[i-1]){continue;}
            int L=i+1;
            int R=len-1;
            while(L<R){
                if(nums[i]+nums[L]+nums[R]==0){
                    res.push_back({nums[i],nums[L],nums[R]});
                    while(L<R && nums[L]==nums[L+1]){L++;}
                    while(L<R && nums[R]==nums[R-1]){R--;}
                    L++;
                    R--;
                }
                else if(nums[i]+nums[L]+nums[R]<0){L++;}
                else{R--;}
            }
        }
        return res;
    }
};

Python:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res=[]
        nums.sort()
        len_nums=len(nums)
        for i in range(len_nums):
            if nums[i]>0:
                break
            if i>0 and nums[i]==nums[i-1]:
                continue
            L=i+1
            R=len_nums-1
            while L<R:
                if nums[i]+nums[L]+nums[R]==0:
                    res.append([nums[i],nums[L],nums[R]])
                    while L<R and nums[L]==nums[L+1]:
                        L+=1
                    while L<R and nums[R]==nums[R-1]:
                        R-=1
                    L+=1
                    R-=1
                elif nums[i]+nums[L]+nums[R]<0:
                    L+=1
                else:
                    R-=1
        return res
        

单循环+哈希做法+外部去重

哈希思路:

数组遍历循环每一个元素,对于该元素,在该元素的右侧进行【两数之和=0-该元素】的降维处理。可参考:力扣hot1--哈希-CSDN博客

代码如下:

C++:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        
        sort(nums.begin(),nums.end());
        
        int len=nums.size();
        vector<vector<int>> res;
        for(int i=0;i<len-2;i++){
            if(nums[i]>0){break;}
            if(i>0 && nums[i]==nums[i-1]){continue;}
            unordered_map<int,int> hmap;
            int target=-nums[i];
            int temp_last=0x3f3f3f3f;
            for(int j=i+1;j<len;j++){
                int temp=target-nums[j];
                if(hmap.find(temp)!=hmap.end()){
                    res.push_back({nums[i],nums[j],temp});
                }
                else{
                    hmap[nums[j]]=1;
                }
            }
        }
        set<vector<int>> s(res.begin(),res.end());
        res.assign(s.begin(),s.end());
        return res;
    }
};

Python:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        len_nums=len(nums)

        res=[]

        for i in range(len_nums-2):
            if nums[i]>0:
                break
            if i>0 and nums[i]==nums[i-1]:
                continue
            hmap={}
            target=-nums[i]
            temp_last=0x3f3f3f3f
            for j in range(i+1,len_nums):
                temp=target-nums[j]
                if temp in hmap:
                    res.append([nums[i],nums[j],temp])
                else:
                    hmap[nums[j]]=1
        s=set(tuple(x) for x in res)
        res=[list(x) for x in s]
        return res

Python中的去重:

s=set(tuple(x) for x in res)
res=[list(x) for x in s]

单循环+哈希做法+内部去重

可能脑子一时瓦特了,没有想到直接内部去重(这里就不附代码啦,仅讲述思想):

当确定元素 i 后,用指针 j 遍历 i 之后的元素,遇到和前面重复的元素就跳过(记得这里已经排序了哦),再和哈希表转换成两数之和~

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值