算法学习-Leetcode(一)—— 三数之和

文章目录

  • 前言
  • 一、暴力解法
  • 二、排序+双指针解法
    • 1.排序 + 双指针
    • 2.C++版本
  • 总结


前言

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

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


一、暴力解法

看到题目依据条件求和,我第一时间想到的就是暴力解法,遍历数组,寻找适合条件的数据(惭愧惭愧,自身实力拉胯,只能先解决问题再优化问题),当我付诸实际的时候,暴力解法确实很符合逻辑,写的也很快,但是问题出现了,题目要求不能出现重复的解,我使用暴力解法,截、解出来是全部解,难免有重复,尝试了一些解决办法依旧不太行,只好看了题解,发现大佬们就是大佬,利用排序和双指针的算法,逻辑通俗易懂,还完美的解决了题目。暴力解法我就不贴出来献丑了。

二、排序+双指针解法

1.排序 + 双指针

本题的难点在于如何去除重复解。

算法流程:
1、特判,对于数组长度 nn,如果数组为 null 或者数组长度小于 3,返回 []。
2、对数组进行排序。
3、遍历排序后数组:
4、若 nums[i]>0:因为已经排序好,所以后面不可能 有三个数加和等于 00,直接返回结果。
5、对于重复元素:跳过,避免出现重复解
令左指针 L=i+1,右指针 R=n-1,当 L 6、当 nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
若和大于 00,说明 nums[R]nums[R] 太大,R 左移
若和小于 00,说明 nums[L]nums[L] 太小,L 右移

三元数排序双指针算法流程

代码如下(示例):

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-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=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res

作者:wu_yan_zu
链接:https://leetcode-cn.com/problems/3sum/solution/pai-xu-shuang-zhi-zhen-zhu-xing-jie-shi-python3-by/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2.C++版本

大佬写了题解思路,又写了python例程,我要是还不会那也太丢人了,参考了题解评论里面一位大哥写的C++版,利用C++也是通过了这道题。(简单的加了点注释,配合思路看更佳)。
代码如下(示例):


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
       vector<vector<int>> ans;
       //数组内元素小于3个,直接返回
       if(nums.size()<3)return ans;
       //数组排序
       sort(nums.begin(),nums.end());
       //排序后,如何全是正数,那么不可能有三个数之和为零了
       if(nums[0]>0)return ans;
       int i = 0;
       while(i < nums.size()){
           if(nums[i]>0)break;
           int Left = i+1;
           int Right = nums.size()-1;
           
           while(Left < Right){
               //防溢出
                long long x = static_cast<long long>(nums[i]);
                long long y = static_cast<long long>(nums[Left]);
                long long z = static_cast<long long>(nums[Right]);

                if(x+y+z>0){
                    Right--;
                }else if(x+y+z<0){
                    Left++;
                }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--;
                }
              
           }
             while(i<nums.size()-1&&nums[i]==nums[i+1]){
                        i++;
                    }
             i++;

   }
           return ans; 
       }

};


总结

1、作为一名未来的嵌入式工程师,我用的更多的可能是C,更多的是C的基础语法。但是对于这些面向对象也只会一些基础语法,更多的函数库和多样的封装好的库函数所知甚少,使用了这些库函数才发现直接调用是真的香。

2、在学习嵌入式的工程中可能算法的用武之地不多,但是学习一些算法,却可以提高个人的四位和解决问题的方式,对于做一个项目,解决一个问题,尝试用另外的方法很重要,解决问题的方式在一代代更新,人也在不断的进步。

3、学习一些算法其实也是在理解计算机思维的方式,对于一个问题,我认为首先解决问题,再优化问题,当然对于有一定实力的人来说,边解决边优化是更好的选择。理解计算机思维才能更好的优化自己写的代码。所以学习算法也很重要也是必不可少的。

4、学习的路上,你我共勉。

你可能感兴趣的:(算法,笔记,算法,c++,leetcode)