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;
}
};
//main
Interface* 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 -Wall
main: binid1 binid3
./binid1
./binid3
binid1: id1.cpp
g++ ${CXXFLAGS} id1.cpp -o binid1
binid3: id3.cpp
g++ ${CXXFLAGS} id3.cpp -o binid3