基于c++11泛型编程开发一个LeetCode本地开发测试组件

来源:互联网 发布:瑞安法院淘宝拍卖网 编辑:程序博客网 时间:2024/06/06 23:19

LeetCode初次接触感觉还不错,重点是可以对比讨论共同实现的一段代码,https://leetcode.com。

处理复杂问题不适合在OJ上直接开发,本地调试更简单。暂时(我想应该会有)未发现可以直接拿来运行的框架,自己简单实现一个,未来发现更好的再补充。

注意:只以用c++11,g++编译选项-std=c++11

一个需要两个文件,下载文件

leetcode.h 包含一些流程控制和通用api(临时写的,需要时补全)

main.cpp 实现一些差异化接口即可

功能:执行指定的数据的测试,自动进行5组随机测试

验证:可以人工核验,也可以指定一个确定的通过代码,对比校验另一下

用法 : class Q1 : public Solution<RetType, ParamList>

RetType表示接口返回类型,具体题目具体替换,不要用引用,不然模板有冲突

ParamList是逗号间隔的所有函数参数列表,这里使用了不定参数模板

实现基类所有纯虚函数

后文给出了第一题和第3题的示例Demo。


一、leetcode.h

#include <iostream>#include <random>#include <map>#include <unordered_map>#include <cassert>#include <algorithm>#include <cstring>using namespace std;class Interface{public:        virtual void RandomTest(uniform_int_distribution<int>& u, default_random_engine& e) = 0;};template<typename RT, typename ...ARGS>class Solution : virtual public Interface{        typedef RT (Solution::*deal_fun_t)(ARGS...);        //定义5个回调算法        virtual RT FUN_NAME_0(ARGS...) { return RT(); }        virtual RT FUN_NAME_1(ARGS...) { return RT(); }        virtual RT FUN_NAME_2(ARGS...) { return RT(); }        virtual RT FUN_NAME_3(ARGS...) { return RT(); }        virtual RT FUN_NAME_4(ARGS...) { return RT(); }        virtual RT FUN_NAME_5(ARGS...) { return RT(); }        deal_fun_t m_fun[5];        //        virtual bool CheckRst(RT&, RT&, ARGS...) const = 0;        virtual void DumpInput(ARGS...) = 0;        //        bool m_debug;        int m_id;public:        void SetConf(int id, bool debug) { m_id =id; m_debug = debug; }        //构造初始化指定算法        Solution(int no = 0)        {                m_fun[0] = &Solution::FUN_NAME_0;                m_fun[1] = &Solution::FUN_NAME_1;                m_fun[2] = &Solution::FUN_NAME_2;                m_fun[3] = &Solution::FUN_NAME_3;                m_fun[4] = &Solution::FUN_NAME_4;                m_fun[5] = &Solution::FUN_NAME_5;        }        //测试并打印相关信息        void Test(ARGS...arg)        {                cout << "----------------" << endl;                DumpInput(arg...);                auto rst1 = FUN_NAME_0(arg...);                auto rst2 = (this->*m_fun[m_id])(arg...);                if(CheckRst(rst1, rst2, arg...))                        cout << "succ" << endl;                else                {                        cout << "fail" << endl;                        assert(!m_debug);                }        }        //公共库存        //随机vector        vector<int> RandomVector(uniform_int_distribution<int>& u, default_random_engine& e, int min)        {                int len = u(e)+min;                vector<int> data(len);                for(int i = 0; i < len; i++)                        data[i] = u(e);                return data;        }        //随机字符串        string RandomString(uniform_int_distribution<int>& u, default_random_engine& e, int min)        {                int len = u(e)+1;                static char s_str[] = "abcdefghijklmnopqrstuvwxvzABCDEFGHIJKLMNOPQRSTUVWXVZ";                char* ptr = s_str, *end=s_str+52;                string rst;                for(int i = 0; i < len; i++)                {                        ptr += u(e);                        if(ptr >= end)                                ptr = s_str;                        rst += (char)ptr[0];                }                return rst;        }        //vector<int>转字符串        string VecToStr(vector<int>& arr, char sep)        {                string str;                char buf[32];                for(auto &i : arr)                {                        sprintf(buf, "%d%c", i, sep);                        str += buf;                }                return str;        }};//mainInterface* GetObj(int argc, char* argv[], char* env[]);int main(int argc, char* argv[], char* env[]){        Interface* s = GetObj(argc, argv, env);        if(s == nullptr)                return 0;        //随机测试        uniform_int_distribution<int> u(0, 9);        default_random_engine e;        e.seed(time(0));        for(int i = 0; i < 5; i++)                      //随机测试5组                s->RandomTest(u, e);        return 0;}

第一题示例:

#include "leetcode.h"//use class Q1 : public Solution<RetType, ParamList>class Q1 : public Solution<int, string>{public:        Q1(int id, bool debug = true)        {                SetConf(id, debug);        }        //一次随机测试        void RandomTest(uniform_int_distribution<int>& u, default_random_engine& e) override        {                Test(RandomString(u, e, 0));        }        //输出输入信息        void DumpInput(string str) override        {                cout << "input: " << str << endl;        }        //输出字符串化以比较  r0是标准函数返回结果, r1是自定义函数结果        bool CheckRst(int& r0, int& r1, string s) const override        {                cout << "rst " << r0 << "," << r1 << endl;                return r0 == r1;        }        int FUN_NAME_0(string s) override        {                vector<int> pos(127, -1);                int max = 0;                int repeat = -1;                int len = s.length();                for(int i = 0; i < len; i++)                {                        if(pos[s[i]] > repeat)                                repeat = pos[s[i]];                        pos[s[i]] = i;                        int len = i - repeat;                        if(len > max)                                max = len;                }                return max;        }        int FUN_NAME_1(string s) override        {                char c[128];                memset(c, 0, sizeof(c));                const char* p = s.c_str();                int len1 = 0, max = 0;                while(*p != '\0')                {                        int pos = (char)*p;                        if(c[pos] != 0)                        {                                while(p[-len1] != *p)                                {                                        pos = p[-len1];                                        --c[pos];                                        --len1;                                }                                pos = p[-len1];                                --c[pos];                                --len1;                        }                        pos = *p;                        c[pos]++;                        p++;                        len1++;                        if(max < len1)                                max = len1;                }                return max;        }};Interface* GetObj(int argc, char* argv[], char* env[]){        Q1* s = new Q1(1, false);                                               //指定使用1号算法        //返回之前可以进行一些内部测试        s->Test("heecagga");        s->Test("eecdb");        s->Test("dfhgd");        s->Test("abcabcbb");        s->Test("bbbbb");        s->Test("pwwkew");        return s;}


第三题示例

#include "leetcode.h"//use class Q1 : public Solution<RetType, ParamList>class Q3 : public Solution<vector<int>, vector<int>, int>{public:        Q3(int id, bool debug = true)        {                SetConf(id, debug);        }        //一次随机测试        void RandomTest(uniform_int_distribution<int>& u, default_random_engine& e) override        {                Test(RandomVector(u, e, 2), u(e));        }        //输出输入信息        void DumpInput(vector<int> nums, int target) override        {                cout << "sum: " << target << " | " << VecToStr(nums, ' ') << endl;        }        //输出字符串化以比较  r0是标准函数返回结果, r1是自定义函数结果        bool CheckRst(vector<int>& r0, vector<int>& r1, vector<int> nums, int target) const override        {                cout << r0[0] << "," << r0[1] << endl << r1[0] << "," << r1[1] << endl;                return nums[r1[0]] + nums[r1[1]] == nums[r0[0]] + nums[r0[1]];  //1和2结果对比                //return (nums[r1[0]] + nums[r1[1]] == target) && (nums[r0[0]] + nums[r0[1]] == target) //全量校验以避免参考答案有误        }        //算法1,普通算法,a+b=target,遍历一次数组,每个数,即可能是a,也可能是b,将a起来。如果找到了当前数的a,则成功        //9ms 54.37,  再提交2次,6ms和12ms        vector<int> FUN_NAME_0(vector<int> nums, int target) override        {                unordered_map<int, int> subs;                const int max = nums.size();                for(int i = 0; i < max; i++)                {                        auto it = subs.find(target-nums[i]);                        if(it != subs.end())                                return vector<int> {it->second, i};                        subs[nums[i]] = i;                }                return vector<int> {-1, -1};        }        //算法2,改进最佳答案,用map同时实现排序和反查,降低反查代价,损耗一些排序性能(相对快速排序)        //18ms, 41.35%, 并没有成功,原因是数据量小的情况下,得不偿失        vector<int> FUN_NAME_1(vector<int> nums, int target) override        {                multimap<int, int> org_pos;                for(size_t i = 0; i < nums.size(); i++)                        org_pos.insert(pair<int,int>(nums[i], i));                auto it_beg = org_pos.begin();                auto it_end = --org_pos.end();                while(it_beg != it_end)                {                        int val = it_beg->first + it_end->first;                        if(val == target)                        {                                if(it_beg->second < it_end->second)                                        return vector<int> {it_beg->second, it_end->second};                                else                                        return vector<int> {it_end->second, it_beg->second};                        }                        if(val > target)                                it_end--;                        else if(val < target)                                it_beg++;                }                return vector<int> {-1, -1};        }};Interface* GetObj(int argc, char* argv[], char* env[]){        Q3* s = new Q3(1, false);                                               //指定使用1号算法        //返回之前可以进行一些内部测试        //s.Test(vector<int> {3,3}, 6);         //指定的固定测试数据        //s.Test(vector<int> {2,7,11,15}, 9);        return s;}


一个非常临时的Makefile

CXXFLAGS= -std=c++11 -g -Wallmain: binid1 binid3        ./binid1        ./binid3binid1: id1.cpp        g++ ${CXXFLAGS} id1.cpp -o binid1binid3: id3.cpp        g++ ${CXXFLAGS} id3.cpp -o binid3


阅读全文
0 0
原创粉丝点击