LeetCode算法练习之三数之和

32 篇文章 0 订阅

和之前的两数之和问题一样,这个问题也可以直接三重循环直接莽穿,但是这算法时间复杂度太大了,O(n^3)的时间复杂度一旦遇到1000位的数组就要循环10亿次,几万位的话时间够泡一杯java了。

这个问题有两种解法,时间复杂度都是O(n^2),包括散列表查找法和双指针法。 

散列表法当然就是之前搞两数之和算法的最优解法,然而幸亏我提前看了讨论区说明这种方法会超时,就没有试验,不然就会写老半天程序最后答案还超时心态爆炸。其实,散列表的查询虽然是线性时间,但是散列表对空间占用非常大,而且碰撞处理也会拖慢它的查找时间使得查找的效率变慢。

然后我就使用了双指针法,先对整个数组进行排序,然后具体原理看两数之和就可以了。之前还有一篇专门写双指针的文章。就是一个指针移动使结果变大,一个使得结果变小。

但是!再次读题,会发现题目要求答案不能包含重复的组。就算结果在程序中算出了两次,最后返回的数组中也只能有一个。刚刚发现这个问题的时候,我认为这个问题很好解决,只要在最后再添加一个小程序来判断解是否在数组中就可以了。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if(nums.size()<3) return {};
        sort(nums.begin(), nums.end());
        int lptr=0;
        int rptr=0;
        int target=0;
        vector<vector<int>> res;
        for(int i=0;i<nums.size()-2;i++){
            target=-nums[i];
            lptr=i+1;
            rptr=nums.size()-1;
            while(rptr>lptr){
                if(nums[lptr]+nums[rptr]>target){
                    rptr--;
                }else if(nums[lptr]+nums[rptr]<target){
                    lptr++;
                }else{
                    bool isbreak=false;
                    for(int a=0;a<res.size();a++){
                        if(res[a][0]==nums[i]&&res[a][1]==nums[lptr]&&res[a][2]==nums[rptr]) isbreak=true;
                    }
                    if(!isbreak) 
                    res.push_back({nums[i],nums[lptr],nums[rptr]});
                    lptr++;
                    rptr--;
                }
            }
        }
        return res;
    }
};

题目确实可以这样解出来,但是这样做,最终的时间评分只有5%具体原因,我估计就是最后一小段程序拖慢了时间。

假设有一个输入是[0,0,0,0,0,0,0,0,0.....,0](上千个0),这时判断是否有重复元素的程序循环的次数可想而知非常多,可以把时间复杂度拖到O(n^3)。

所以就要对程序进行再优化。我们想可不可以在循环的时候就判断出结果是否重复,去掉最后判断结果是否重复的程序?考虑一个现象,数组既然已经排序好了,那么同样的元素必定相邻。那么如果这次循环的元素和上次一样,这次循环就包括了上次循环的所有可能情况,这次循环就不能执行,必须马上跳出以保证结果中同样的答案只出现一次。改进代码如下:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if(nums.size()<3) return {};
        sort(nums.begin(), nums.end());
        int lptr=0;
        int rptr=0;
        int target=0;
        vector<vector<int>> res;
        for(int i=0;i<nums.size()-2;i++){
            target=-nums[i];
            if(nums[i]>0) break;
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            lptr=i+1;
            rptr=nums.size()-1;
            while(rptr>lptr){
                if(nums[lptr]+nums[rptr]>target){
                    rptr--;
                    while(lptr<rptr&&nums[rptr]==nums[rptr+1]) rptr--;
                }else if(nums[lptr]+nums[rptr]<target){
                    lptr++;
                    while(lptr<rptr&&nums[lptr]==nums[lptr-1]) lptr++;
                }else{/*
                    bool isbreak=false;
                    for(int a=0;a<res.size();a++){
                        if(res[a][0]==nums[i]&&res[a][1]==nums[lptr]&&res[a][2]==nums[rptr]) isbreak=true;
                    }
                    if(!isbreak) 
                    */
                    res.push_back({nums[i],nums[lptr],nums[rptr]});
                    lptr++;
                    while(lptr<rptr&&nums[lptr]==nums[lptr-1]) lptr++;
                    rptr--;
                    while(lptr<rptr&&nums[rptr]==nums[rptr+1]) rptr--;
                }
            }
        }
        return res;
    }
};

 

结果达到了81%,说明算法还有优化空间,但是做题的时候心态爆炸,没有想出来,试一下解答区大佬的优化技巧(++i的使用一看就知道是C++编程老手)

 

貌似编译器会对这样的程序进行优化以达到更加的效率,这点我就不懂了。。。不过既然时间复杂度是一样的,差距也没多少,这些内容的研究还是次要的。掌握主要的算法知识才是重点。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 类leetcode算法在线编译的答题系统源码可以包含以下几个关键部分: 1. 用户认证和管理:系统需要提供用户认证功能,允许用户进行注册、登录和注销操作。可以使用据库存储用户信息,并对密码进行加密保护。通过认证,用户可以保存和管理自己的答题记录和排名。 2. 题目管理:系统需要提供题目的增删改查功能。每个题目包含一个标题、题目描述、输入要求、输出要求和示例等信息。可以使用据库存储题目信息,并提供相应的接口供管理员进行管理。 3. 代码编辑和编译:系统需要提供一个代码编辑器,让用户可以编写算法代码。编辑器需要支持常见的编程语言,如C++、Java、Python等,并提供语法高亮和自动补全等功能。用户可以在编辑器中编写代码,并进行编译和运行测试。 4. 测试用例和结果判断:系统需要提供一个测试用例管理功能,允许管理员为每个题目设置多个测试用例。用户可以选择运行自己的代码,并查看运行结果。系统会自动判断用户代码的输出是否符合预期结果,并给出相应的反馈。 5. 答题记录和排名:系统需要记录用户的答题记录,包括题目信息、提交时间、编译结果和运行结果等。用户可以查看自己的答题记录,同时系统也会根据答题情况进行排名,展示最高得分和排名前几名的用户信息。 6. 用户交流和讨论:系统可以提供一个讨论区或论坛功能,供用户之间互相交流和提问。用户可以就题目的解法、算法思路等进行讨论,并给出相应的评论和回答。 以上是一个类leetcode算法在线编译的答题系统源码的基本结构和功能要求。具体实现可以根据需求进行适当调整和拓展。 ### 回答2: 类leetcode算法在线编译的答题系统源码是一个用于提供算法练习和在线编译运行的系统。该系统以类似leetcode的方式,提供了一系列算法题目,并给出了题目描述和输入输出示例。 源码中的核心功能包括题目列表、题目详情、代码编辑和编译运行等功能。用户可以在题目列表页面选择自己想要练习的题目,点击进入题目详情页面查看题目描述和示例。在代码编辑页面,用户可以输入自己的解答代码,并点击编译运行按钮执行代码,并查看运行结果。 在源码编写过程中,需要使用一些必要的技术和工具。前端开发可以使用HTML、CSS和JavaScript,通过前端框架进行页面布局和交互处理,提供用户友好的界面。后端开发可以使用一种后端框架,如node.js或Python等,设计据库模型和处理请求的逻辑。同时需要使用一种编译器或解释器,支持对用户输入的代码进行编译运行,并返回结果。 在源码的实现过程中,需要考虑安全性和容错性。为了防止用户恶意代码或非法操作,可以使用输入验证和代码沙箱技术对用户输入进行过滤和安全检查。对于异常情况,可以通过异常处理机制捕获并给出相应的错误提示信息。 总之,类leetcode算法在线编译的答题系统源码应当具备题目管理、代码编辑和编译运行功能,并注意安全性和用户友好性。通过实现这样一个系统,可以帮助用户提升算法能力并加深对编程语言的理解和应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值