### Leetcode 给出的接口

Leetcode给出的接口基本就是一个在Solution类里的方法签名。比如，下面就是题目Two Sum的接口。

public class Solution {
public int[] twoSum(int[] nums, int target) {

}
}

new

### Problem - Solution - Test 框架

• 每题都是一个Problem
• 每个Problem可以有好几个解题方法Solution
• Problem里提供一个Solution的注册表
• Test类就在注册表里加载不同的Solution进行测试

• SolutionProblem类的内部抽象类。
• 不同的解题方法Solution1,Solution2等等都继承自Solution抽象类。
• Problem类内部的注册表是面向Solution抽象类的。
• Test也是Problem类的静态内部套嵌类，Test类握有一个Problem的实例。
• Test的操作也是面向Solution抽象类的。

/**
* Leetcode - Algorithm - AnyProblem
*/
package com.ciaoshen.leetcode;
import java.util.*;
import com.ciaoshen.leetcode.myUtils.*;

/**
*  Each problem is initialized with 3 solutions.
*  You can expand more solutions.
*  Before using your new solutions, don't forget to register them to the solution registry.
*/
class AnyProblem implements Problem {
private Map<Integer,Solution> solutions = new HashMap<>(); // solutions registry
// register solutions HERE...
private AnyProblem() {
register(new Solution1());
register(new Solution2());
register(new Solution3());
}
private abstract class Solution {
private int id = 0;
abstract public boolean isStrobogrammatic(String num);
}
private class Solution1 extends Solution {
{ super.id = 1; }
// implement your solution's method HERE...
public boolean isStrobogrammatic(String num) {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}

private class Solution2 extends Solution {
{ super.id = 2; }
// implement your solution's method HERE...
public boolean isStrobogrammatic(String num) {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}

private class Solution3 extends Solution {
{ super.id = 3; }
// implement your solution's method HERE...
public boolean isStrobogrammatic(String num) {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}
// you can expand more solutions HERE if you want...

/**
* register a solution in the solution registry
* return false if this type of solution already exist in the registry.
*/
private boolean register(Solution s) {
return (solutions.put(s.id,s) == null)? true : false;
}
/**
* chose one of the solution to test
* return null if solution id does not exist
*/
private Solution solution(int id) {
return solutions.get(id);
}

private static class Test {
private AnyProblem problem = new AnyProblem();
private Solution solution = null;

/** initialize your testcases HERE... */
//... ...
//... ...
//... ...
//... ...
//... ...
//... ...

// call method in solution
private void call() {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}

// public API of Test interface
public void test(int i) {
solution = problem.solution(i);
if (solution == null) { System.out.println("Sorry, [id:" + i + "] doesn't exist!"); return; }

/** involk call() method HERE */
/** involk call() method HERE */
/** involk call() method HERE */

call();

/** involk call() method HERE */
/** involk call() method HERE */
/** involk call() method HERE */
}
}
public static void main(String[] args) {
Test test = new Test();
test.test(1); // call by the solution id
}
}

### 模板和解析器

.txt文本文件里写下下面的文本（模板的模板）。在所有用到类名的地方用_CLASS_标记，用到方法签名的地方用_METHOD_标记。

/**
* Leetcode - Algorithm - _CLASS_
*/
package com.ciaoshen.leetcode;
import java.util.*;
import com.ciaoshen.leetcode.myUtils.*;

/**
*  Each problem is initialized with 3 solutions.
*  You can expand more solutions.
*  Before using your new solutions, don't forget to register them to the solution registry.
*/
class _CLASS_ implements Problem {
private Map<Integer,Solution> solutions = new HashMap<>(); // solutions registry
// register solutions HERE...
private _CLASS_() {
register(new Solution1());
register(new Solution2());
register(new Solution3());
}
private abstract class Solution {
private int id = 0;
abstract _METHOD_;
}
private class Solution1 extends Solution {
{ super.id = 1; }
// implement your solution's method HERE...
_METHOD_ {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}

private class Solution2 extends Solution {
{ super.id = 2; }
// implement your solution's method HERE...
_METHOD_ {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}

private class Solution3 extends Solution {
{ super.id = 3; }
// implement your solution's method HERE...
_METHOD_ {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}
}
// you can expand more solutions HERE if you want...

/**
* register a solution in the solution registry
* return false if this type of solution already exist in the registry.
*/
private boolean register(Solution s) {
return (solutions.put(s.id,s) == null)? true : false;
}
/**
* chose one of the solution to test
* return null if solution id does not exist
*/
private Solution solution(int id) {
return solutions.get(id);
}

private static class Test {
private _CLASS_ problem = new _CLASS_();
private Solution solution = null;

/** initialize your testcases HERE... */
//... ...
//... ...
//... ...
//... ...
//... ...
//... ...

// call method in solution
private void call() {
/** write your code HERE */
// ... ...
// ... ...
// ... ...
// ... ...
// ... ...
}

// public API of Test interface
public void test(int i) {
solution = problem.solution(i);
if (solution == null) { System.out.println("Sorry, [id:" + i + "] doesn't exist!"); return; }

/** involk call() method HERE */
/** involk call() method HERE */
/** involk call() method HERE */

call();

/** involk call() method HERE */
/** involk call() method HERE */
/** involk call() method HERE */
}
}
public static void main(String[] args) {
Test test = new Test();
test.test(1); // call by the solution id
}
}

Java没有宏替换，所以需要写个解析器，替换所有_CLASS__METHOD_标记，就可以生成类的源文件的模板，

/**
* To generate template of a class under "~/github/leetcode/java/src/com/ciaoshen/leetcode/"
*/
package com.ciaoshen.leetcode.template;
import java.util.*;
import java.io.*;

class ProblemGenerator {
/**
* @param args [classname and method]
* args[0]: classname
* args[1]: method
*/
private static final String CLASS_FLAG = "_CLASS_";
private static final String METHOD_FLAG = "_METHOD_";
public static void main(String[] args) {
if (args.length < 4) { // defense
System.out.println("Parameters not enough!"); return;
}
String srcpath = args[0]; // template source path
String despath = args[1]; // new class path
String classname = args[2]; // calss name
String method = args[3]; // method signature

String content = "";
try {
StringBuilder sb = new StringBuilder();
try {
while (true) {
if (line == null) { break; }
line = line.replaceAll(CLASS_FLAG,classname);
line = line.replaceAll(METHOD_FLAG,method);
sb.append(line+"\n");
}
content = sb.toString();
} finally {
br.close();
}
} catch (FileNotFoundException fnfe) {
System.out.println("Check file path: " + fnfe);
} catch (IOException ioe) {
System.out.println("Error when reading file " + ioe);
}

try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(despath)));
try {
bw.write(content,0,content.length());
} finally {
bw.close();
}
} catch (IOException ioe) {
System.out.println("Error when writing file " + ioe);
}
}
}

#!/bin/sh
#############################################################
# Parameters
# 每次修改 CLASS_NAME 和 METHOD
# CLASS_NAME: 希望生成类的名字。
# METHOD: Leetcode给出的Solution类里的主要方法签名。
#
# 例如：
# 对问题Two Sum我想写一个叫TwoSum的类
# Leetcode给出的方法签名如下：
# 	public class Solution {
#   		public int[] twoSum(int[] nums, int target) {
#
#    		}
#	}
#
# 我应该把  CLASS_NAME 和 METHOD 改为：
# CLASS_NAME: "TwoSum"
# METHOD: "public int[] twoSum(int[] nums, int target)"
##############################################################

# basic dir
BASE_DIR="/Users/Wei/github/leetcode/java/template"
CLASS_DIR="${BASE_DIR}/bin" SOURCE_DIR="${BASE_DIR}/src"
PACKAGE="com.ciaoshen.leetcode.template"

# template
SOURCE_PATH="${SOURCE_DIR}/com/ciaoshen/leetcode/template" # file FILE_NAME="ProblemGenerator" FILE="${FILE_NAME}.java"

# parameters
################################################
# 请修改下面  CLASS_NAME  和  METHOD  两个参数
################################################
CLASS_NAME="AnyProblem"
METHOD="public boolean isStrobogrammatic(String num)"
TEMPLATE_FILE="${BASE_DIR}/problem.txt" DESTINATION="/Users/Wei/github/leetcode/java/src/com/ciaoshen/leetcode/${CLASS_NAME}.java"

# compile
javac -d ${CLASS_DIR} -cp${CLASS_DIR} -sourcepath ${SOURCE_DIR} "${SOURCE_PATH}/${FILE}" # run java -cp${CLASS_DIR} "${PACKAGE}.${FILE_NAME}" ${TEMPLATE_FILE}${DESTINATION} ${CLASS_NAME} "${METHOD}"

new