- tray = new ArrayList<>();
+ public Tray(String caption) {
+ super(caption);
}
-
public void add(Item item){
tray.add(item);
}
-
}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListFactory.java b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListFactory.java
new file mode 100644
index 0000000..a11b773
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListFactory.java
@@ -0,0 +1,29 @@
+package com.leosanqing.abstractfactory.listfactory;
+
+import com.leosanqing.abstractfactory.factory.Factory;
+import com.leosanqing.abstractfactory.factory.Link;
+import com.leosanqing.abstractfactory.factory.Page;
+import com.leosanqing.abstractfactory.factory.Tray;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 21:11
+ *
+ * ListFactory 只是抽象工厂的其中一个实现工厂,功能是输出列表样式
+ */
+public class ListFactory extends Factory {
+ @Override
+ public Link createLink(String caption, String url) {
+ return new ListLink(caption,url);
+ }
+
+ @Override
+ public Tray createTray(String caption) {
+ return new ListTray(caption);
+ }
+
+ @Override
+ public Page createPage(String title, String author) {
+ return new ListPage(title,author);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListLink.java b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListLink.java
new file mode 100644
index 0000000..87659d5
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListLink.java
@@ -0,0 +1,18 @@
+package com.leosanqing.abstractfactory.listfactory;
+
+import com.leosanqing.abstractfactory.factory.Link;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 21:13
+ */
+public class ListLink extends Link {
+ public ListLink(String caption, String url) {
+ super(caption, url);
+ }
+
+ @Override
+ public String makeHTML() {
+ return "
" + caption + " \n";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListPage.java b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListPage.java
new file mode 100644
index 0000000..fb95eb1
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListPage.java
@@ -0,0 +1,33 @@
+package com.leosanqing.abstractfactory.listfactory;
+
+import com.leosanqing.abstractfactory.factory.Item;
+import com.leosanqing.abstractfactory.factory.Page;
+
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 21:26
+ */
+public class ListPage extends Page {
+ public ListPage(String title, String author) {
+ super(title, author);
+ }
+
+ @Override
+ public String makeHTML() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("" + title + " \n");
+ buffer.append("\n");
+ buffer.append("" + title + " ");
+ buffer.append("\n");
+ for (Item item : content) {
+ buffer.append(item.makeHTML());
+ }
+ buffer.append(" \n");
+ buffer.append("" + author + " ");
+ buffer.append("\n");
+
+ return buffer.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListTray.java b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListTray.java
new file mode 100644
index 0000000..0c90d81
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/listfactory/ListTray.java
@@ -0,0 +1,28 @@
+package com.leosanqing.abstractfactory.listfactory;
+
+import com.leosanqing.abstractfactory.factory.Item;
+import com.leosanqing.abstractfactory.factory.Tray;
+
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 21:20
+ */
+public class ListTray extends Tray {
+ public ListTray(String caption) {
+ super(caption);
+ }
+
+ @Override
+ public String makeHTML() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("\n").append(caption).append("\n");
+ buffer.append("\n");
+ for (Item item : tray) {
+ buffer.append(item.makeHTML());
+ }
+ buffer.append(" \n").append(" \n");
+ return buffer.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableFactory.java b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableFactory.java
new file mode 100644
index 0000000..c1f4025
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableFactory.java
@@ -0,0 +1,27 @@
+package com.leosanqing.abstractfactory.tablefactory;
+
+import com.leosanqing.abstractfactory.factory.Factory;
+import com.leosanqing.abstractfactory.factory.Link;
+import com.leosanqing.abstractfactory.factory.Page;
+import com.leosanqing.abstractfactory.factory.Tray;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 23:33
+ */
+public class TableFactory extends Factory {
+ @Override
+ public Link createLink(String caption, String url) {
+ return new TableLink(caption,url);
+ }
+
+ @Override
+ public Tray createTray(String caption) {
+ return new TableTray(caption);
+ }
+
+ @Override
+ public Page createPage(String title, String author) {
+ return new TablePage(title,author);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableLink.java b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableLink.java
new file mode 100644
index 0000000..8da395d
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableLink.java
@@ -0,0 +1,18 @@
+package com.leosanqing.abstractfactory.tablefactory;
+
+import com.leosanqing.abstractfactory.factory.Link;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 23:00
+ */
+public class TableLink extends Link {
+ public TableLink(String caption, String url) {
+ super(caption, url);
+ }
+
+ @Override
+ public String makeHTML() {
+ return " " + caption + " ";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TablePage.java b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TablePage.java
new file mode 100644
index 0000000..f3784c3
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TablePage.java
@@ -0,0 +1,30 @@
+package com.leosanqing.abstractfactory.tablefactory;
+
+import com.leosanqing.abstractfactory.factory.Item;
+import com.leosanqing.abstractfactory.factory.Page;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 23:27
+ */
+public class TablePage extends Page {
+ public TablePage(String title, String author) {
+ super(title, author);
+ }
+
+ @Override
+ public String makeHTML() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(""+title+" \n");
+ buffer.append("\n");
+ buffer.append(""+title+" \n");
+ buffer.append("\n");
+ for (Item item : content) {
+ buffer.append(item.makeHTML());
+ }
+ buffer.append("
\n");
+ buffer.append(""+author+" ");
+ buffer.append("\n");
+ return buffer.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableTray.java b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableTray.java
new file mode 100644
index 0000000..6ec3ec3
--- /dev/null
+++ b/designPattern/src/com/leosanqing/abstractFactory/tablefactory/TableTray.java
@@ -0,0 +1,30 @@
+package com.leosanqing.abstractfactory.tablefactory;
+
+import com.leosanqing.abstractfactory.factory.Item;
+import com.leosanqing.abstractfactory.factory.Tray;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-14 23:18
+ */
+public class TableTray extends Tray {
+ public TableTray(String caption) {
+ super(caption);
+ }
+
+ @Override
+ public String makeHTML() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("");
+ buffer.append("");
+ buffer.append(" colspan=\"").append(tray.size()).append("\">").append(caption).append(" ");
+ buffer.append(" \n");
+ buffer.append("\n");
+ for (Item item : tray) {
+ buffer.append(item.makeHTML());
+ }
+ buffer.append("
");
+ buffer.append(" ");
+ return buffer.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/adapter/extend/Banner.java b/designPattern/src/com/leosanqing/adapter/extend/Banner.java
index 05855d8..25b84b1 100644
--- a/designPattern/src/com/leosanqing/adapter/extend/Banner.java
+++ b/designPattern/src/com/leosanqing/adapter/extend/Banner.java
@@ -1,16 +1,21 @@
package com.leosanqing.adapter.extend;
-public class Banner {
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 17:51
+ */
+public class Banner {
private String string;
- public Banner (String string){
+
+ public Banner(String string) {
this.string = string;
}
- public void showWithParen(){
+ public void showWithParen() {
System.out.println("(" + string + ")");
}
- public void showWithAster(){
+ public void showWithAster() {
System.out.println("*" + string + "*");
}
}
diff --git a/designPattern/src/com/leosanqing/adapter/extend/Print.java b/designPattern/src/com/leosanqing/adapter/extend/Print.java
index fdadaf0..c8d3840 100644
--- a/designPattern/src/com/leosanqing/adapter/extend/Print.java
+++ b/designPattern/src/com/leosanqing/adapter/extend/Print.java
@@ -1,6 +1,10 @@
package com.leosanqing.adapter.extend;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 17:50
+ */
public interface Print {
- public abstract void printWeak();
- public abstract void printStrong();
+ void printWeak();
+ void printStrong();
}
diff --git a/designPattern/src/com/leosanqing/adapter/extend/PrintBanner.java b/designPattern/src/com/leosanqing/adapter/extend/PrintBanner.java
index 754bbcc..26b7f08 100644
--- a/designPattern/src/com/leosanqing/adapter/extend/PrintBanner.java
+++ b/designPattern/src/com/leosanqing/adapter/extend/PrintBanner.java
@@ -1,5 +1,11 @@
package com.leosanqing.adapter.extend;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 17:54
+ *
+ * 这是使用继承来实现 Adapter。等下看下二者的区别
+ */
public class PrintBanner extends Banner implements Print {
public PrintBanner(String string) {
super(string);
diff --git a/designPattern/src/com/leosanqing/adapter/extend/Test.java b/designPattern/src/com/leosanqing/adapter/extend/Test.java
index 771b14a..7d1105e 100644
--- a/designPattern/src/com/leosanqing/adapter/extend/Test.java
+++ b/designPattern/src/com/leosanqing/adapter/extend/Test.java
@@ -2,7 +2,7 @@
public class Test {
public static void main(String[] args) {
- PrintBanner printBanner = new PrintBanner("hello world");
+ Print printBanner = new PrintBanner("hello world");
printBanner.printWeak();
printBanner.printStrong();
}
diff --git a/designPattern/src/com/leosanqing/adapter/trust/Banner.java b/designPattern/src/com/leosanqing/adapter/trust/Banner.java
index 33dd7ac..3b35302 100644
--- a/designPattern/src/com/leosanqing/adapter/trust/Banner.java
+++ b/designPattern/src/com/leosanqing/adapter/trust/Banner.java
@@ -1,16 +1,20 @@
package com.leosanqing.adapter.trust;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:14
+ */
public class Banner {
private String string;
- public Banner(String string){
+
+ public Banner(String string) {
this.string = string;
}
-
- public void showWithParen(){
- System.out.println("("+string+")");
+ public void showWithParen() {
+ System.out.println("(" + string + ")");
}
- public void showWithAster(){
+ public void showWithAster() {
System.out.println("*" + string + "*");
}
}
diff --git a/designPattern/src/com/leosanqing/adapter/trust/Print.java b/designPattern/src/com/leosanqing/adapter/trust/Print.java
index fad1883..0e072d1 100644
--- a/designPattern/src/com/leosanqing/adapter/trust/Print.java
+++ b/designPattern/src/com/leosanqing/adapter/trust/Print.java
@@ -1,5 +1,9 @@
package com.leosanqing.adapter.trust;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:13
+ */
public abstract class Print {
public abstract void printWeak();
public abstract void printStrong();
diff --git a/designPattern/src/com/leosanqing/adapter/trust/PrintBanner.java b/designPattern/src/com/leosanqing/adapter/trust/PrintBanner.java
index dcd37fd..fdeb92b 100644
--- a/designPattern/src/com/leosanqing/adapter/trust/PrintBanner.java
+++ b/designPattern/src/com/leosanqing/adapter/trust/PrintBanner.java
@@ -1,10 +1,17 @@
package com.leosanqing.adapter.trust;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:15
+ */
public class PrintBanner extends Print {
private Banner banner;
- public PrintBanner(String string){
- banner = new Banner(string);
+
+ public PrintBanner(String string) {
+ this.banner = new Banner(string);
}
+
+
@Override
public void printWeak() {
banner.showWithParen();
@@ -13,6 +20,5 @@ public void printWeak() {
@Override
public void printStrong() {
banner.showWithAster();
-
}
}
diff --git a/designPattern/src/com/leosanqing/bridge/CountDisplay.java b/designPattern/src/com/leosanqing/bridge/CountDisplay.java
new file mode 100644
index 0000000..2657242
--- /dev/null
+++ b/designPattern/src/com/leosanqing/bridge/CountDisplay.java
@@ -0,0 +1,23 @@
+package com.leosanqing.bridge;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-23 21:29
+ */
+public class CountDisplay extends Display {
+
+ public CountDisplay(DisplayImpl display) {
+ super(display);
+ }
+
+
+ public void multiDisplay(int count){
+ open();
+ for (int i = 0; i < count; i++) {
+ print();
+ }
+ close();
+ }
+
+
+}
diff --git a/designPattern/src/com/leosanqing/bridge/Display.java b/designPattern/src/com/leosanqing/bridge/Display.java
new file mode 100644
index 0000000..8205f0b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/bridge/Display.java
@@ -0,0 +1,41 @@
+package com.leosanqing.bridge;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-23 08:38
+ * |
+ * Bridge方法是将类的功能层次和类的实现层次相分离的模式
+ *
+ * 我们看这个Display类,他的这些方法实质上调用的是 DisplayImpl类的方法
+ *
+ * 看到这个有没有想到之前我们学过的Adapter模式的委托方法。
+ *
+ * 除了没有提前将它的各种方法声明,其实都是一样,
+ *
+ * 看这个像不像是 Adapter + Template 模式
+ */
+public class Display {
+ private DisplayImpl display;
+
+ public Display(DisplayImpl display){
+ this.display = display;
+ }
+
+ public void open(){
+ display.rawOpen();
+ }
+
+ public void print(){
+ display.rawPrint();
+ }
+
+ public void close(){
+ display.rawClose();
+ }
+
+ public void display(){
+ open();
+ print();
+ close();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/bridge/DisplayImpl.java b/designPattern/src/com/leosanqing/bridge/DisplayImpl.java
new file mode 100644
index 0000000..8500894
--- /dev/null
+++ b/designPattern/src/com/leosanqing/bridge/DisplayImpl.java
@@ -0,0 +1,11 @@
+package com.leosanqing.bridge;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-23 21:25
+ */
+public abstract class DisplayImpl {
+ public abstract void rawOpen();
+ public abstract void rawPrint();
+ public abstract void rawClose();
+}
diff --git a/designPattern/src/com/leosanqing/bridge/Main.java b/designPattern/src/com/leosanqing/bridge/Main.java
new file mode 100644
index 0000000..8c6228b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/bridge/Main.java
@@ -0,0 +1,19 @@
+package com.leosanqing.bridge;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 08:50
+ */
+public class Main {
+ public static void main(String[] args) {
+ Display display = new Display(new StringDisplay("leosanqing"));
+ Display display1 = new CountDisplay(new StringDisplay("pipi"));
+ CountDisplay countDisplay = new CountDisplay(new StringDisplay("hello world"));
+
+ display.display();
+ display1.display();
+
+ countDisplay.display();
+ countDisplay.multiDisplay(3);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/bridge/StringDisplay.java b/designPattern/src/com/leosanqing/bridge/StringDisplay.java
new file mode 100644
index 0000000..786572b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/bridge/StringDisplay.java
@@ -0,0 +1,28 @@
+package com.leosanqing.bridge;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-23 21:31
+ */
+public class StringDisplay extends DisplayImpl {
+ private String string;
+
+ public StringDisplay(String string) {
+ this.string = string;
+ }
+
+ @Override
+ public void rawOpen() {
+ System.out.println("=====open====");
+ }
+
+ @Override
+ public void rawPrint() {
+ System.out.println(string);
+ }
+
+ @Override
+ public void rawClose() {
+ System.out.println("=====close====");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/builder/Builder.java b/designPattern/src/com/leosanqing/builder/Builder.java
index 336d624..069735c 100644
--- a/designPattern/src/com/leosanqing/builder/Builder.java
+++ b/designPattern/src/com/leosanqing/builder/Builder.java
@@ -2,11 +2,19 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-03 19:50
+ * @Date: 2019-09-06 21:42
+ * builder 模式中,我们在这个类中声明所有的方法
+ *
+ * 和template模式不同的是:
+ * builder组装的具体流程被封装在 Director类中
+ * 而template 模式则被封装到 父类中
*/
public abstract class Builder {
+ // 创建标题
public abstract void makeTitle(String title);
- public abstract void makeString(String string);
+ // 创建字符串
+ public abstract void makeString(String str);
+ // 创建 条目
public abstract void makeItems(String[] items);
public abstract void close();
}
diff --git a/designPattern/src/com/leosanqing/builder/Director.java b/designPattern/src/com/leosanqing/builder/Director.java
index 5bb991b..6a191e5 100644
--- a/designPattern/src/com/leosanqing/builder/Director.java
+++ b/designPattern/src/com/leosanqing/builder/Director.java
@@ -2,18 +2,16 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-03 19:52
+ * @Date: 2019-09-06 21:57
*/
public class Director {
private Builder builder;
-
- public Director(Builder builder) {
+ public Director(Builder builder){
this.builder = builder;
}
-
public void construct(){
- builder.makeTitle("Greeting");
- builder.makeString("从早上至下午");
+ builder.makeTitle("Hello");
+ builder.makeString("从早上到下午");
builder.makeItems(new String[]{
"早上好",
"下午好"
@@ -25,6 +23,5 @@ public void construct(){
"再见"
});
builder.close();
-
}
}
diff --git a/designPattern/src/com/leosanqing/builder/HTMLBuilder.java b/designPattern/src/com/leosanqing/builder/HTMLBuilder.java
index bf3187d..30d4848 100644
--- a/designPattern/src/com/leosanqing/builder/HTMLBuilder.java
+++ b/designPattern/src/com/leosanqing/builder/HTMLBuilder.java
@@ -2,49 +2,47 @@
import java.io.FileWriter;
import java.io.IOException;
-import java.io.PipedWriter;
import java.io.PrintWriter;
/**
* @Author: leosanqing
- * @Date: 2019-08-03 20:04
+ * @Date: 2019-09-06 22:10
*/
public class HTMLBuilder extends Builder {
private String filename;
private PrintWriter writer;
+
@Override
public void makeTitle(String title) {
- filename = title+".html";
+ filename = title + ".html";
try {
writer = new PrintWriter(new FileWriter(filename));
} catch (IOException e) {
e.printStackTrace();
}
- writer.println(""+filename+" ");
- writer.println(""+title+" ");
+ writer.println("" + title + " ");
}
@Override
- public void makeString(String string) {
- writer.println(""+ string +"
");
+ public void makeString(String str) {
+ writer.println("" + str + "
");
}
@Override
public void makeItems(String[] items) {
writer.println("");
- for (int i = 0; i < items.length; i++) {
- writer.println(""+items[i]+" ");
+ for (String item : items) {
+ writer.println(""+item+" ");
}
writer.println(" ");
}
-
@Override
public void close() {
writer.println("");
- writer.close();
}
+
public String getResult(){
return filename;
}
diff --git a/designPattern/src/com/leosanqing/builder/Test.java b/designPattern/src/com/leosanqing/builder/Main.java
similarity index 54%
rename from designPattern/src/com/leosanqing/builder/Test.java
rename to designPattern/src/com/leosanqing/builder/Main.java
index d32d41a..f6f9bb6 100644
--- a/designPattern/src/com/leosanqing/builder/Test.java
+++ b/designPattern/src/com/leosanqing/builder/Main.java
@@ -2,37 +2,33 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-03 20:28
+ * @Date: 2019-09-10 22:09
*/
-public class Test {
+public class Main {
public static void main(String[] args) {
- if (args.length != 1) {
+ if(args.length != 1){
usage();
System.exit(0);
}
-
- if (args[0].equals("plain")) {
+ if(args[0].equals("plain")){
TextBuilder textBuilder = new TextBuilder();
Director director = new Director(textBuilder);
director.construct();
String result = textBuilder.getResult();
System.out.println(result);
- } else if (args[0].equals("html")) {
+ }else if(args[0].equals("html")){
HTMLBuilder htmlBuilder = new HTMLBuilder();
Director director = new Director(htmlBuilder);
director.construct();
- String result = htmlBuilder.getResult();
- System.out.println(result + "文件编写完成");
- } else {
- usage();
- System.exit(0);
+ String filename = htmlBuilder.getResult();
+ System.out.println(filename+"编写完成");
}
+ }
- }
- public static void usage() {
- System.out.println("Usage: java Test plain");
- System.out.println("Usage: java Test html");
+ public static void usage(){
+ System.out.println("Usage: java main plain 编写纯文本文档");
+ System.out.println("Usage: java main html 编写html文档");
}
}
diff --git a/designPattern/src/com/leosanqing/builder/TextBuilder.java b/designPattern/src/com/leosanqing/builder/TextBuilder.java
index 169a2c2..7eeb9bc 100644
--- a/designPattern/src/com/leosanqing/builder/TextBuilder.java
+++ b/designPattern/src/com/leosanqing/builder/TextBuilder.java
@@ -2,38 +2,37 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-03 19:57
+ * @Date: 2019-09-06 22:02
+ * 将其以文本格式输出
*/
public class TextBuilder extends Builder {
-
private StringBuffer buffer = new StringBuffer();
@Override
public void makeTitle(String title) {
- buffer.append("====================\n");
- buffer.append("『" + title + "』\n");
+ buffer.append("=================\n");
+ buffer.append("『").append(title).append("』\n");
buffer.append("\n");
}
@Override
- public void makeString(String string) {
- buffer.append('-' + string + "\n");
+ public void makeString(String str) {
+ buffer.append('$').append(str).append("\n");
buffer.append("\n");
}
@Override
public void makeItems(String[] items) {
- for (int i = 0; i < items.length; i++) {
- buffer.append(" *"+items[i]+"\n");
+ for (String item : items) {
+ buffer.append(" *").append(item).append("\n");
}
buffer.append("\n");
}
@Override
public void close() {
- buffer.append("===================\n");
+ buffer.append("=================\n");
}
-
public String getResult(){
return buffer.toString();
}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/LimitSupport.java b/designPattern/src/com/leosanqing/chainofresponsibility/LimitSupport.java
new file mode 100644
index 0000000..8f26688
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/LimitSupport.java
@@ -0,0 +1,21 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-23 23:10
+ */
+
+public class LimitSupport extends Support {
+ private int limit;
+
+ protected LimitSupport(String name, int limit) {
+ super(name);
+ this.limit = limit;
+ }
+
+ @Override
+ protected boolean resolve(Trouble trouble) {
+
+ return trouble.getNum() < limit;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/Main.java b/designPattern/src/com/leosanqing/chainofresponsibility/Main.java
new file mode 100644
index 0000000..9f76c5f
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/Main.java
@@ -0,0 +1,21 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 21:55
+ */
+public class Main {
+ public static void main(String[] args) {
+ Support alice = new NoSupport("Alice");
+ Support bob = new LimitSupport("Bob", 100);
+ Support charlie = new SpecialSupport("Charlie", 429);
+ Support diana = new LimitSupport("Diana", 200);
+ Support elmo = new OddSupport("Elmo");
+ Support fred = new LimitSupport("Fred", 300);
+ alice.setNextSupport(bob).setNextSupport(charlie).setNextSupport(diana)
+ .setNextSupport(elmo).setNextSupport(fred);
+ for (int i = 0; i < 500; i+= 33) {
+ alice.support(new Trouble(i));
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/NoSupport.java b/designPattern/src/com/leosanqing/chainofresponsibility/NoSupport.java
new file mode 100644
index 0000000..eb51d73
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/NoSupport.java
@@ -0,0 +1,17 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-23 23:10
+ */
+public class NoSupport extends Support {
+
+ protected NoSupport(String name) {
+ super(name);
+ }
+
+ @Override
+ protected boolean resolve(Trouble trouble) {
+ return false;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/OddSupport.java b/designPattern/src/com/leosanqing/chainofresponsibility/OddSupport.java
new file mode 100644
index 0000000..ed73713
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/OddSupport.java
@@ -0,0 +1,16 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-23 23:12
+ */
+public class OddSupport extends Support {
+ protected OddSupport(String name) {
+ super(name);
+ }
+
+ @Override
+ protected boolean resolve(Trouble trouble) {
+ return trouble.getNum() % 2 == 1;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/SpecialSupport.java b/designPattern/src/com/leosanqing/chainofresponsibility/SpecialSupport.java
new file mode 100644
index 0000000..c3b164e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/SpecialSupport.java
@@ -0,0 +1,18 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-23 23:12
+ */
+public class SpecialSupport extends Support {
+ private int num;
+ protected SpecialSupport(String name,int num) {
+ super(name);
+ this.num = num;
+ }
+
+ @Override
+ protected boolean resolve(Trouble trouble) {
+ return trouble.getNum() == num;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/Support.java b/designPattern/src/com/leosanqing/chainofresponsibility/Support.java
new file mode 100644
index 0000000..cf7d9c4
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/Support.java
@@ -0,0 +1,47 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-22 08:15
+ */
+public abstract class Support {
+ private String name;
+ private Support next;
+
+ // 生成实例
+ protected Support(String name) {
+ this.name = name;
+ }
+
+ // 要推卸给的对象
+ public Support setNextSupport(Support next) {
+ this.next = next;
+ return next;
+ }
+
+ public final void support(Trouble trouble) {
+ if (resolve(trouble)) {
+ done(trouble);
+ } else if (next != null) {
+ next.support(trouble);
+ } else {
+ fail(trouble);
+ }
+ }
+
+ private void fail(Trouble trouble) {
+ System.out.println(trouble + " can not be resolved");
+ }
+
+ private void done(Trouble trouble) {
+ System.out.println(trouble + " is resolved by " + this + ".");
+ }
+
+ protected abstract boolean resolve(Trouble trouble);
+
+
+ @Override
+ public String toString() {
+ return "[" + name + "]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/chainofresponsibility/Trouble.java b/designPattern/src/com/leosanqing/chainofresponsibility/Trouble.java
new file mode 100644
index 0000000..93717e7
--- /dev/null
+++ b/designPattern/src/com/leosanqing/chainofresponsibility/Trouble.java
@@ -0,0 +1,23 @@
+package com.leosanqing.chainofresponsibility;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-22 08:12
+ */
+public class Trouble {
+ private int num;
+
+ public Trouble(int num) {
+ this.num = num;
+ }
+ public int getNum(){
+ return num;
+ }
+
+ @Override
+ public String toString() {
+ return "[Trouble" +
+ + num +
+ "]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/Main.java b/designPattern/src/com/leosanqing/command/Main.java
new file mode 100644
index 0000000..ca095a8
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/Main.java
@@ -0,0 +1,11 @@
+package com.leosanqing.command;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 11:32
+ */
+public class Main {
+ public static void main(String[] args) {
+ new MyFrame("Sample");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/MyFrame.java b/designPattern/src/com/leosanqing/command/MyFrame.java
new file mode 100644
index 0000000..15a3bc9
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/MyFrame.java
@@ -0,0 +1,95 @@
+package com.leosanqing.command;
+
+import com.leosanqing.command.command.Command;
+import com.leosanqing.command.command.MacroCommand;
+import com.leosanqing.command.drawer.DrawCanvas;
+import com.leosanqing.command.drawer.DrawCommand;
+
+import javax.swing.*;
+import java.awt.event.*;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 11:33
+ */
+public class MyFrame extends JFrame implements ActionListener,
+ MouseMotionListener, WindowListener {
+ private MacroCommand history = new MacroCommand();
+
+ private DrawCanvas canvas = new DrawCanvas(400,400,history);
+
+ private JButton clearButton = new JButton("clear");
+
+ public MyFrame(String title){
+ super(title);
+
+ this.addWindowListener(this);
+ this.addMouseMotionListener(this);
+ clearButton.addActionListener(this);
+
+ Box buttonBox = new Box(BoxLayout.X_AXIS);
+ buttonBox.add(clearButton);
+ Box mainBox = new Box(BoxLayout.Y_AXIS);
+ mainBox.add(buttonBox);
+ mainBox.add(canvas);
+ getContentPane().add(mainBox);
+
+ pack();
+ setVisible(true);
+ }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if(e.getSource() == clearButton){
+ history.clear();
+ canvas.repaint();
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+// System.out.println("15646546465");
+ Command command = new DrawCommand(canvas,e.getPoint());
+ history.append(command);
+ command.execute();
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+// System.out.println(e.getPoint());
+ }
+
+ @Override
+ public void windowOpened(WindowEvent e) {
+
+ }
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+
+ @Override
+ public void windowClosed(WindowEvent e) {
+
+ }
+
+ @Override
+ public void windowIconified(WindowEvent e) {
+
+ }
+
+ @Override
+ public void windowDeiconified(WindowEvent e) {
+
+ }
+
+ @Override
+ public void windowActivated(WindowEvent e) {
+
+ }
+
+ @Override
+ public void windowDeactivated(WindowEvent e) {
+
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/command/Command.java b/designPattern/src/com/leosanqing/command/command/Command.java
new file mode 100644
index 0000000..22edacb
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/command/Command.java
@@ -0,0 +1,10 @@
+package com.leosanqing.command.command;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 10:27
+ */
+public interface Command {
+ void execute();
+
+}
diff --git a/designPattern/src/com/leosanqing/command/command/MacroCommand.java b/designPattern/src/com/leosanqing/command/command/MacroCommand.java
new file mode 100644
index 0000000..474427a
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/command/MacroCommand.java
@@ -0,0 +1,32 @@
+package com.leosanqing.command.command;
+
+import java.util.Stack;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 10:36
+ */
+public class MacroCommand implements Command {
+ private Stack commands = new Stack<>();
+
+ @Override
+ public void execute() {
+ for (Command command : commands) {
+ command.execute();
+ }
+ }
+
+ public void append(Command command) {
+ if (command != this)
+ commands.push(command);
+ }
+
+ public void undo(){
+ if(!commands.empty())
+ commands.pop();
+ }
+
+ public void clear(){
+ commands.clear();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/drawer/DrawCanvas.java b/designPattern/src/com/leosanqing/command/drawer/DrawCanvas.java
new file mode 100644
index 0000000..0936331
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/drawer/DrawCanvas.java
@@ -0,0 +1,33 @@
+package com.leosanqing.command.drawer;
+
+import com.leosanqing.command.command.MacroCommand;
+
+import java.awt.*;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 11:03
+ */
+public class DrawCanvas extends Canvas implements Drawable {
+ private Color color = Color.RED;
+ private int radius = 6;
+ private MacroCommand history;
+
+ public DrawCanvas(int width, int height, MacroCommand history) {
+ setSize(width, height);
+ setBackground(Color.white);
+ this.history = history;
+ }
+
+ public void paint(Graphics g) {
+ history.execute();
+ }
+
+
+ @Override
+ public void draw(int x, int y) {
+ Graphics graphics = getGraphics();
+ graphics.setColor(color);
+ graphics.fillOval(x - radius, y - radius, radius * 2, radius * 2);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/drawer/DrawCommand.java b/designPattern/src/com/leosanqing/command/drawer/DrawCommand.java
new file mode 100644
index 0000000..9f72a9e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/drawer/DrawCommand.java
@@ -0,0 +1,23 @@
+package com.leosanqing.command.drawer;
+
+import com.leosanqing.command.command.Command;
+
+import java.awt.*;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 10:52
+ */
+public class DrawCommand implements Command {
+ protected Drawable drawable;
+ private Point position;
+
+ public DrawCommand(Drawable drawable,Point position){
+ this.drawable = drawable;
+ this.position = position;
+ }
+ @Override
+ public void execute() {
+ drawable.draw(position.x,position.y);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/command/drawer/Drawable.java b/designPattern/src/com/leosanqing/command/drawer/Drawable.java
new file mode 100644
index 0000000..495399a
--- /dev/null
+++ b/designPattern/src/com/leosanqing/command/drawer/Drawable.java
@@ -0,0 +1,10 @@
+package com.leosanqing.command.drawer;
+
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 10:50
+ */
+public interface Drawable {
+ void draw(int x, int y);
+}
diff --git a/designPattern/src/com/leosanqing/composite/Directory.java b/designPattern/src/com/leosanqing/composite/Directory.java
new file mode 100644
index 0000000..b0ff1c3
--- /dev/null
+++ b/designPattern/src/com/leosanqing/composite/Directory.java
@@ -0,0 +1,45 @@
+package com.leosanqing.composite;
+
+import java.util.ArrayList;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 08:24
+ */
+public class Directory extends Entry {
+ private String name;
+ private ArrayList directory = new ArrayList<>();
+
+ public Directory(String name) {
+ this.name = name;
+
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getSize() {
+ int size = 0;
+
+ for (Entry entry : directory) {
+ size += entry.getSize();
+ }
+ return size;
+ }
+
+ public void add(Entry entry){
+ directory.add(entry);
+
+ }
+
+ @Override
+ protected void printList(String prefix) {
+ System.out.println(prefix + "/" + this.toString());
+ for (Entry entry : directory) {
+ entry.printList(prefix + "/" + name);
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/composite/Entry.java b/designPattern/src/com/leosanqing/composite/Entry.java
new file mode 100644
index 0000000..67401be
--- /dev/null
+++ b/designPattern/src/com/leosanqing/composite/Entry.java
@@ -0,0 +1,27 @@
+package com.leosanqing.composite;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 08:16
+ */
+public abstract class Entry {
+ public abstract String getName();
+
+ public abstract int getSize();
+
+ public void add(Entry entry) throws FileTreatmentException {
+ throw new FileTreatmentException();
+ }
+
+
+ public void printList() {
+ printList("");
+ }
+
+ protected abstract void printList(String prefix);
+
+ public String toString() {
+ return getName() + "(" + getSize() + ")";
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/composite/File.java b/designPattern/src/com/leosanqing/composite/File.java
new file mode 100644
index 0000000..afa0f25
--- /dev/null
+++ b/designPattern/src/com/leosanqing/composite/File.java
@@ -0,0 +1,30 @@
+package com.leosanqing.composite;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 08:22
+ */
+public class File extends Entry {
+ private String name;
+ private int size;
+
+ public File(String name, int size) {
+ this.name = name;
+ this.size = size;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getSize() {
+ return size;
+ }
+
+ @Override
+ protected void printList(String prefix) {
+ System.out.println(prefix + "/" + this.toString());
+ }
+}
diff --git a/designPattern/src/com/leosanqing/composite/FileTreatmentException.java b/designPattern/src/com/leosanqing/composite/FileTreatmentException.java
new file mode 100644
index 0000000..294a007
--- /dev/null
+++ b/designPattern/src/com/leosanqing/composite/FileTreatmentException.java
@@ -0,0 +1,14 @@
+package com.leosanqing.composite;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 08:19
+ */
+public class FileTreatmentException extends Throwable {
+ public FileTreatmentException(){}
+
+
+ public FileTreatmentException(String msg){
+ super(msg);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/composite/Main.java b/designPattern/src/com/leosanqing/composite/Main.java
new file mode 100644
index 0000000..27ae14a
--- /dev/null
+++ b/designPattern/src/com/leosanqing/composite/Main.java
@@ -0,0 +1,41 @@
+package com.leosanqing.composite;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 11:32
+ */
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Making root entries....");
+ Directory root = new Directory("root");
+ Directory usr = new Directory("usr");
+ Directory tmp = new Directory("tmp");
+ Directory bin = new Directory("bin");
+
+ root.add(usr);
+ root.add(tmp);
+ root.add(bin);
+
+ bin.add(new File("vi",100));
+ bin.add(new File("latex",500));
+
+ root.printList();
+
+ System.out.println();
+ System.out.println("Making usr entries");
+
+ Directory leosanqing = new Directory("leosanqing");
+ Directory pipi = new Directory("pipi");
+ Directory leo = new Directory("leo");
+ usr.add(leosanqing);
+ usr.add(pipi);
+ usr.add(leo);
+
+ leosanqing.add(new File("Design Pattern.pdf",1000));
+ leosanqing.add(new File("Understanding The JVM.pdf",2000));
+ pipi.add(new File("First Love.mobi",400));
+ leo.add(new File("XXX.avi",10000));
+
+ root.printList();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/Border.java b/designPattern/src/com/leosanqing/decorator/Border.java
new file mode 100644
index 0000000..2922177
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/Border.java
@@ -0,0 +1,17 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-23 19:24
+ *
+ * 在这里 这个 Border也使用了 委托
+ *
+ * 但是委托的具体动作交给了 子类实现
+ */
+public abstract class Border extends Display {
+ protected Display display;
+
+ protected Border(Display display) {
+ this.display = display;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/Display.java b/designPattern/src/com/leosanqing/decorator/Display.java
new file mode 100644
index 0000000..7d4c115
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/Display.java
@@ -0,0 +1,18 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 22:07
+ */
+public abstract class Display {
+ public abstract int getColumns();
+ public abstract int getRows();
+
+ public abstract String getRowText(int rows);
+
+ public final void show(){
+ for (int i = 0; i < getRows(); i++) {
+ System.out.println(getRowText(i));
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/FullBorder.java b/designPattern/src/com/leosanqing/decorator/FullBorder.java
new file mode 100644
index 0000000..07e52f9
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/FullBorder.java
@@ -0,0 +1,41 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 22:33
+ */
+public class FullBorder extends Border {
+ protected FullBorder(Display display) {
+ super(display);
+ }
+
+ @Override
+ public int getColumns() {
+ return 1 + display.getColumns() + 1;
+ }
+
+ @Override
+ public int getRows() {
+ return 1 + display.getRows() + 1;
+ }
+
+ @Override
+ public String getRowText(int rows) {
+ // 上边框
+ if (rows == 0) {
+ return "+" + makeLine('-', display.getColumns()) + "+";
+ } else if (rows == display.getRows() + 1) { // 下边框
+ return "+" + makeLine('-', display.getColumns()) + "+";
+ } else {
+ return "|" + display.getRowText(rows-1) + "|";
+ }
+ }
+
+ private String makeLine(char c, int columns) {
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < columns; i++) {
+ buffer.append(c);
+ }
+ return buffer.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/Main.java b/designPattern/src/com/leosanqing/decorator/Main.java
new file mode 100644
index 0000000..03bf74a
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/Main.java
@@ -0,0 +1,29 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 19:38
+ */
+public class Main {
+ public static void main(String[] args) {
+ Display b1 = new StringDisplay("leosanqing");
+ Display b2 = new SideBorder(b1,'#');
+ Display b3 = new FullBorder(b2);
+
+ b1.show();
+ b2.show();
+ b3.show();
+
+ new SideBorder(
+ new FullBorder(
+ new FullBorder(
+ new SideBorder(
+ new FullBorder(
+ new StringDisplay("pipi")
+ ),'*'
+ )
+ )
+ ),'/'
+ ).show();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/SideBorder.java b/designPattern/src/com/leosanqing/decorator/SideBorder.java
new file mode 100644
index 0000000..61e790f
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/SideBorder.java
@@ -0,0 +1,29 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 22:13
+ */
+public class SideBorder extends Border {
+ private char borderChar;
+
+ protected SideBorder(Display display, char borderChar) {
+ super(display);
+ this.borderChar = borderChar;
+ }
+
+ @Override
+ public int getColumns() {
+ return 1 + display.getColumns() + 1;
+ }
+
+ @Override
+ public int getRows() {
+ return display.getRows();
+ }
+
+ @Override
+ public String getRowText(int rows) {
+ return borderChar + display.getRowText(rows) + borderChar;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/decorator/StringDisplay.java b/designPattern/src/com/leosanqing/decorator/StringDisplay.java
new file mode 100644
index 0000000..ebe20fd
--- /dev/null
+++ b/designPattern/src/com/leosanqing/decorator/StringDisplay.java
@@ -0,0 +1,30 @@
+package com.leosanqing.decorator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-24 22:10
+ */
+public class StringDisplay extends Display {
+ private String string;
+
+ public StringDisplay(String string) {
+ this.string = string;
+ }
+
+ @Override
+ public int getColumns() {
+ return string.getBytes().length;
+ }
+
+ @Override
+ public int getRows() {
+ return 1;
+ }
+
+ @Override
+ public String getRowText(int rows) {
+ if (rows == 0)
+ return string;
+ return null;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/facade/Main.java b/designPattern/src/com/leosanqing/facade/Main.java
new file mode 100644
index 0000000..9b6609b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/facade/Main.java
@@ -0,0 +1,15 @@
+package com.leosanqing.facade;
+
+import com.leosanqing.facade.pagemakeer.PageMaker;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-16 22:45
+ *
+ * 对外只提供了 下面这一个接口,我们只需要传入两个参数,他就能完成剩下的所有步骤
+ */
+public class Main {
+ public static void main(String[] args) {
+ PageMaker.makeWelcomePage("leosanqing@qq.com","welcome.html");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/facade/pagemakeer/Database.java b/designPattern/src/com/leosanqing/facade/pagemakeer/Database.java
new file mode 100644
index 0000000..fd87c51
--- /dev/null
+++ b/designPattern/src/com/leosanqing/facade/pagemakeer/Database.java
@@ -0,0 +1,30 @@
+package com.leosanqing.facade.pagemakeer;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-16 08:18
+ *
+ * 从邮箱地址中获取用户名的类,在这个例子中我们只是从一个文本中获取,并不是链接数据库
+ */
+public class Database {
+
+ // 防止其他类new实例,因此把这个构造函数私有化
+ private Database() {}
+
+
+ // 外部直接调用这个静态函数,类似于单例模式
+ public static Properties getProperties(String dbname) {
+ String filename = dbname + ".txt";
+ Properties properties = new Properties();
+ try {
+ properties.load(new FileInputStream(filename));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return properties;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/facade/pagemakeer/HtmlWriter.java b/designPattern/src/com/leosanqing/facade/pagemakeer/HtmlWriter.java
new file mode 100644
index 0000000..dfc7d28
--- /dev/null
+++ b/designPattern/src/com/leosanqing/facade/pagemakeer/HtmlWriter.java
@@ -0,0 +1,45 @@
+package com.leosanqing.facade.pagemakeer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-16 08:25
+ *
+ * 我们在这里封装了 页面的格式。输入相应函数和参数,直接构造成相应的页面的东西
+ */
+public class HtmlWriter {
+ private Writer writer;
+
+ public HtmlWriter(Writer writer) {
+ this.writer = writer;
+ }
+
+ public void title(String title) throws IOException {
+ writer.write("");
+ writer.write("
");
+ writer.write("" + title + " ");
+ writer.write("");
+ writer.write("\n");
+ writer.write("" + title + " \n");
+ }
+
+ public void paragraph(String msg) throws IOException {
+ writer.write("" + msg + "
");
+ }
+
+ public void link(String href, String caption) throws IOException {
+ paragraph("" + caption + " ");
+ }
+ public void mailto(String mailaddr,String username) throws IOException{
+ link("mailto:"+mailaddr,username);
+ }
+
+ public void close() throws IOException{
+ writer.write("");
+ writer.write("");
+ writer.close();
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/facade/pagemakeer/PageMaker.java b/designPattern/src/com/leosanqing/facade/pagemakeer/PageMaker.java
new file mode 100644
index 0000000..e3c84ed
--- /dev/null
+++ b/designPattern/src/com/leosanqing/facade/pagemakeer/PageMaker.java
@@ -0,0 +1,33 @@
+package com.leosanqing.facade.pagemakeer;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-16 22:38
+ *
+ * 这里封装我们调用数据库和调用HtmlWriter的逻辑,我们只需要传入两个参数,他就能完成页面的编写
+ */
+public class PageMaker {
+ private PageMaker() {
+ }
+
+ public static void makeWelcomePage(String mailaddr, String filename) {
+ try {
+ Properties properties = Database.getProperties("maildata");
+ String username = properties.getProperty(mailaddr);
+ HtmlWriter htmlWriter = new HtmlWriter(new FileWriter(filename));
+ htmlWriter.title("Welcome to " + username + "'s page");
+ htmlWriter.paragraph(username + "欢迎来到" + username + "的主页");
+ htmlWriter.paragraph("等你邮件哦");
+
+ htmlWriter.mailto(mailaddr, username);
+ htmlWriter.close();
+ System.out.println(filename + " is created for " + mailaddr + " (" + username + " )");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/factory/Test.java b/designPattern/src/com/leosanqing/factory/Test.java
index 765a8a2..edca9e0 100644
--- a/designPattern/src/com/leosanqing/factory/Test.java
+++ b/designPattern/src/com/leosanqing/factory/Test.java
@@ -1,17 +1,46 @@
package com.leosanqing.factory;
+
+import com.leosanqing.factory.framework.Factory;
import com.leosanqing.factory.framework.Product;
-import com.leosanqing.factory.idcard.IDCard;
+import com.leosanqing.factory.idcard.IDCardFactory;
+import com.leosanqing.factory.idcard.IDCardFactorySingleton;
+
+/**
+ * 我把我自己之前犯得错误写了出来(一开始我没发现,后来才看到)
+ *
+ * 一开始我没有使用工厂模式创建实例,而是使用我们最最常用的方法 new 一个对象
+ *
+ * 工厂方法不用 new 关键字来生成实例,而是调用生成实例的专用方法,
+ * 目的是为了防止 父类和其他具体类耦合
+ */
public class Test {
public static void main(String[] args) {
- Product p1 = new IDCard("小明");
- Product p2 = new IDCard("小红");
- Product p3 = new IDCard("小黑");
+
+/* Factory factory = new IDCardFactory();
+
+ Product p1 = factory.create("小明");
+ Product p2 = factory.create("小红");
+ Product p3 = factory.create("小黑");
+
+// Product p1 = new IDCard("小明");
+// Product p2 = new IDCard("小红");
+// Product p3 = new IDCard("小黑");
p1.use();
p2.use();
p3.use();
+ */
+
+ // 使用单例创建工厂
+ Factory factory = IDCardFactorySingleton.getInstance();
+ Product p1 = factory.create("小明");
+ Product p2 = factory.create("小红");
+ Product p3 = factory.create("小黑");
+ p1.use();
+ p2.use();
+ p3.use();
}
}
diff --git a/designPattern/src/com/leosanqing/factory/framework/Factory.java b/designPattern/src/com/leosanqing/factory/framework/Factory.java
index f6cae0e..360d0ae 100644
--- a/designPattern/src/com/leosanqing/factory/framework/Factory.java
+++ b/designPattern/src/com/leosanqing/factory/framework/Factory.java
@@ -1,12 +1,18 @@
package com.leosanqing.factory.framework;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:30
+ */
public abstract class Factory {
- public final Product create(String string){
- Product product = createProduct(string);
- registerProduct(product);
- return product;
+ // 这里使用Template模式
+ public final Product create(String owner){
+ Product p = createProduct(owner);
+ registerProduct(p);
+ return p;
}
- public abstract Product createProduct(String string);
- public abstract void registerProduct(Product product);
+ protected abstract Product createProduct(String owner);
+ protected abstract void registerProduct(Product product);
}
diff --git a/designPattern/src/com/leosanqing/factory/framework/Product.java b/designPattern/src/com/leosanqing/factory/framework/Product.java
index 0dc148c..fb7ae01 100644
--- a/designPattern/src/com/leosanqing/factory/framework/Product.java
+++ b/designPattern/src/com/leosanqing/factory/framework/Product.java
@@ -1,6 +1,9 @@
package com.leosanqing.factory.framework;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:30
+ */
public abstract class Product {
-
public abstract void use();
}
diff --git a/designPattern/src/com/leosanqing/factory/idcard/IDCard.java b/designPattern/src/com/leosanqing/factory/idcard/IDCard.java
index cae98b6..e29a9d6 100644
--- a/designPattern/src/com/leosanqing/factory/idcard/IDCard.java
+++ b/designPattern/src/com/leosanqing/factory/idcard/IDCard.java
@@ -1,22 +1,27 @@
package com.leosanqing.factory.idcard;
+
import com.leosanqing.factory.framework.Product;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:44
+ */
public class IDCard extends Product {
private String owner;
- public IDCard(String owner){
- System.out.println("开始制作"+owner+ "的IDCard");
- this.owner = owner ;
+ // 因为防止外面直接new实例
+ IDCard(String owner) {
+ System.out.println("制作" + owner + "的IDCard");
+ this.owner = owner;
}
@Override
public void use() {
- System.out.println(owner+"开始使用IDCard");
-
+ System.out.println("正在使用" + owner + "的ID卡");
}
- public String getOwner(){
+ public String getOwner() {
return owner;
}
}
diff --git a/designPattern/src/com/leosanqing/factory/idcard/IDCardFactory.java b/designPattern/src/com/leosanqing/factory/idcard/IDCardFactory.java
index 17b3ceb..7971f02 100644
--- a/designPattern/src/com/leosanqing/factory/idcard/IDCardFactory.java
+++ b/designPattern/src/com/leosanqing/factory/idcard/IDCardFactory.java
@@ -6,20 +6,24 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:51
+ */
public class IDCardFactory extends Factory {
- private List owners = new ArrayList();
+ private List owners = new ArrayList<>();
+
@Override
- public Product createProduct(String string) {
- return new IDCard(string);
+ protected Product createProduct(String owner) {
+ return new IDCard(owner);
}
@Override
- public void registerProduct(Product product) {
-
- owners.add(((IDCard)product).getOwner());
+ protected void registerProduct(Product product) {
+ owners.add(((IDCard) product).getOwner());
}
- public List getOwners(){
+ public List getOwners() {
return owners;
}
}
diff --git a/designPattern/src/com/leosanqing/factory/idcard/IDCardFactorySingleton.java b/designPattern/src/com/leosanqing/factory/idcard/IDCardFactorySingleton.java
new file mode 100644
index 0000000..b7cd5ab
--- /dev/null
+++ b/designPattern/src/com/leosanqing/factory/idcard/IDCardFactorySingleton.java
@@ -0,0 +1,43 @@
+package com.leosanqing.factory.idcard;
+
+import com.leosanqing.factory.framework.Factory;
+import com.leosanqing.factory.framework.Product;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 21:14
+ */
+public class IDCardFactorySingleton extends Factory {
+ private List owners = new ArrayList<>();
+ public volatile static IDCardFactorySingleton instance = null;
+
+ private IDCardFactorySingleton(){}
+
+ public static IDCardFactorySingleton getInstance(){
+ if (instance == null) {
+ synchronized (IDCardFactorySingleton.class){
+ if (instance == null) {
+ instance = new IDCardFactorySingleton();
+ }
+ }
+ }
+ return instance;
+ }
+
+ @Override
+ protected Product createProduct(String owner) {
+ return new IDCard(owner);
+ }
+
+ @Override
+ protected void registerProduct(Product product) {
+ owners.add(((IDCard)product).getOwner());
+ }
+
+ public List getOwners(){
+ return owners;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/factory/idcard/IDCardSingleton.java b/designPattern/src/com/leosanqing/factory/idcard/IDCardSingleton.java
new file mode 100644
index 0000000..5b965a8
--- /dev/null
+++ b/designPattern/src/com/leosanqing/factory/idcard/IDCardSingleton.java
@@ -0,0 +1,37 @@
+package com.leosanqing.factory.idcard;
+
+import com.leosanqing.factory.framework.Product;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 20:56
+ */
+public class IDCardSingleton extends Product {
+ private String owner;
+
+ public static volatile IDCardSingleton instance = null;
+
+ private IDCardSingleton() {
+ }
+
+ public static IDCardSingleton getInstance() {
+ if (instance == null) {
+ synchronized (IDCardSingleton.class) {
+ if (instance == null) {
+ instance = new IDCardSingleton();
+ }
+ }
+ }
+ return instance;
+ }
+
+
+ @Override
+ public void use() {
+ System.out.println("正在使用" + owner + "的IDCard");
+ }
+
+ public String getOwner() {
+ return owner;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/flyweight/BigChar.java b/designPattern/src/com/leosanqing/flyweight/BigChar.java
new file mode 100644
index 0000000..35d4693
--- /dev/null
+++ b/designPattern/src/com/leosanqing/flyweight/BigChar.java
@@ -0,0 +1,42 @@
+package com.leosanqing.flyweight;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-21 09:56
+ *
+ * 读取文件信息
+ */
+public class BigChar {
+ private char charName;
+ private String fontData;
+
+ public BigChar(char charName) {
+ this.charName = charName;
+ try {
+ BufferedReader reader = new BufferedReader(
+ new FileReader("big" + charName + ".txt"));
+ String line;
+ StringBuffer buffer = new StringBuffer();
+ while ((line = reader.readLine()) != null){
+ buffer.append(line).append("\n");
+ }
+ reader.close();
+ this.fontData = buffer.toString();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+
+ this.fontData = charName +"?";
+ }
+ }
+
+ public void print(){
+ System.out.println(fontData);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/flyweight/BigCharFactory.java b/designPattern/src/com/leosanqing/flyweight/BigCharFactory.java
new file mode 100644
index 0000000..640c5d0
--- /dev/null
+++ b/designPattern/src/com/leosanqing/flyweight/BigCharFactory.java
@@ -0,0 +1,50 @@
+package com.leosanqing.flyweight;
+
+import java.util.HashMap;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-21 10:26
+ */
+public class BigCharFactory {
+
+// enum Singleton{
+// INSTANCE;
+// private BigCharFactory instance;
+// private BigCharFactory getInstance(){
+//
+// }
+// }
+
+ private HashMap pool = new HashMap<>();
+
+ private static BigCharFactory instance = null;
+
+ private BigCharFactory() {
+ }
+
+
+ public static BigCharFactory getInstance() {
+ if (instance == null) {
+ synchronized (BigCharFactory.class) {
+ if (instance == null) {
+ instance = new BigCharFactory();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * 使用 synchronized 可以防止 多线程情况下 new 出多个实例
+ */
+ public synchronized BigChar getBigChar(char charName) {
+ BigChar bigChar = pool.get(charName + "");
+ if (bigChar == null) {
+ bigChar = new BigChar(charName);
+ pool.put(charName + "", bigChar);
+ }
+ return bigChar;
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/flyweight/BigString.java b/designPattern/src/com/leosanqing/flyweight/BigString.java
new file mode 100644
index 0000000..74037dc
--- /dev/null
+++ b/designPattern/src/com/leosanqing/flyweight/BigString.java
@@ -0,0 +1,24 @@
+package com.leosanqing.flyweight;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-21 10:41
+ */
+public class BigString {
+ private BigChar[] bigChars;
+
+ public BigString(String string){
+ bigChars = new BigChar[string.length()];
+
+ BigCharFactory factory = BigCharFactory.getInstance();
+ for (int i = 0; i < string.length(); i++) {
+ bigChars[i] = factory.getBigChar(string.charAt(i));
+ }
+ }
+
+ public void print(){
+ for (int i = 0; i < bigChars.length; i++) {
+ bigChars[i].print();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/flyweight/Main.java b/designPattern/src/com/leosanqing/flyweight/Main.java
new file mode 100644
index 0000000..3c25305
--- /dev/null
+++ b/designPattern/src/com/leosanqing/flyweight/Main.java
@@ -0,0 +1,12 @@
+package com.leosanqing.flyweight;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-21 10:52
+ */
+public class Main {
+ public static void main(String[] args) {
+ BigString bigString = new BigString("1212");
+ bigString.print();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/CommandListNode.java b/designPattern/src/com/leosanqing/interpreter/CommandListNode.java
new file mode 100644
index 0000000..957af31
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/CommandListNode.java
@@ -0,0 +1,30 @@
+package com.leosanqing.interpreter;
+
+import java.util.ArrayList;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 14:45
+ */
+public class CommandListNode extends Node {
+ private ArrayList list = new ArrayList<>();
+ @Override
+ public void parse(Context context) throws ParseException {
+ while (true){
+ if(context.currentToken() == null){
+ throw new ParseException("Missing 'end'");
+ }else if(context.currentToken().equals("end")){
+ context.skipToken("end");
+ break;
+ }else{
+ Node commandNode = new CommandNode();
+ commandNode.parse(context);
+ list.add(commandNode);
+ }
+ }
+ }
+
+ public String toString(){
+ return list.toString();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/CommandNode.java b/designPattern/src/com/leosanqing/interpreter/CommandNode.java
new file mode 100644
index 0000000..fcb7c5e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/CommandNode.java
@@ -0,0 +1,25 @@
+package com.leosanqing.interpreter;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 14:57
+ */
+public class CommandNode extends Node {
+ private Node node;
+
+ @Override
+ public void parse(Context context) throws ParseException {
+ if(context.currentToken().equals("repeat")){
+ node = new RepeatCommandNode();
+ node.parse(context);
+ }else{
+ node = new PrimitiveCommandNode();
+ node.parse(context);
+ }
+ }
+
+ public String toString(){
+ return node.toString();
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/Context.java b/designPattern/src/com/leosanqing/interpreter/Context.java
new file mode 100644
index 0000000..500da89
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/Context.java
@@ -0,0 +1,49 @@
+package com.leosanqing.interpreter;
+
+
+import java.util.StringTokenizer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 13:21
+ */
+public class Context {
+ private StringTokenizer tokenizer;
+ private String currentToken;
+
+ public Context(String text) {
+ tokenizer = new StringTokenizer(text);
+ nextToken();
+ }
+
+ public String nextToken() {
+ if (tokenizer.hasMoreElements()) {
+ currentToken = tokenizer.nextToken();
+ } else {
+ currentToken = null;
+ }
+ return currentToken;
+ }
+
+ public String currentToken() {
+ return currentToken;
+ }
+
+ public void skipToken(String token) throws ParseException {
+ if (!token.equals(currentToken)) {
+ throw new ParseException("Warning: " + token + " is expected,but "
+ + currentToken + " is found.");
+ }
+ nextToken();
+ }
+
+ public int currentNumber() throws ParseException {
+ int number = 0;
+ try {
+ number = Integer.parseInt(currentToken);
+ }catch (NumberFormatException e){
+ throw new ParseException("Warning: "+e);
+ }
+ return number;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/Main.java b/designPattern/src/com/leosanqing/interpreter/Main.java
new file mode 100644
index 0000000..ff1b74e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/Main.java
@@ -0,0 +1,33 @@
+package com.leosanqing.interpreter;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 15:16
+ */
+public class Main {
+ public static void main(String[] args) {
+ try {
+ BufferedReader reader = new BufferedReader(
+ new FileReader("program.txt"));
+ String text;
+ while ((text =reader.readLine())!=null){
+ System.out.println("text = \""+text+"\"");
+ Node node = new ProgramNode();
+ node.parse(new Context(text));
+ System.out.println("node = " + node);
+ }
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/Node.java b/designPattern/src/com/leosanqing/interpreter/Node.java
new file mode 100644
index 0000000..14e72ea
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/Node.java
@@ -0,0 +1,10 @@
+package com.leosanqing.interpreter;
+
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 13:18
+ */
+public abstract class Node {
+ public abstract void parse(Context context) throws ParseException;
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/ParseException.java b/designPattern/src/com/leosanqing/interpreter/ParseException.java
new file mode 100644
index 0000000..a80883d
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/ParseException.java
@@ -0,0 +1,11 @@
+package com.leosanqing.interpreter;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 13:46
+ */
+public class ParseException extends Exception {
+ public ParseException(String msg){
+ super(msg);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/PrimitiveCommandNode.java b/designPattern/src/com/leosanqing/interpreter/PrimitiveCommandNode.java
new file mode 100644
index 0000000..0845469
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/PrimitiveCommandNode.java
@@ -0,0 +1,23 @@
+package com.leosanqing.interpreter;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 15:09
+ */
+public class PrimitiveCommandNode extends Node {
+ private String name;
+
+ @Override
+ public void parse(Context context) throws ParseException {
+ name = context.currentToken();
+ context.skipToken(name);
+ if (!name.equals("go") && !name.equals("right")
+ && !name.equals("left")) {
+ throw new ParseException(name+" is undefined");
+ }
+ }
+
+ public String toString(){
+ return name;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/ProgramNode.java b/designPattern/src/com/leosanqing/interpreter/ProgramNode.java
new file mode 100644
index 0000000..2b86185
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/ProgramNode.java
@@ -0,0 +1,23 @@
+package com.leosanqing.interpreter;
+
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 13:19
+ */
+public class ProgramNode extends Node {
+ private Node commandListNode;
+
+ @Override
+ public void parse(Context context) throws ParseException {
+ context.skipToken("program");
+ commandListNode = new CommandListNode();
+ commandListNode.parse(context);
+ }
+
+ public String toString() {
+ return "[program " + commandListNode + "]";
+ }
+
+
+}
diff --git a/designPattern/src/com/leosanqing/interpreter/RepeatCommandNode.java b/designPattern/src/com/leosanqing/interpreter/RepeatCommandNode.java
new file mode 100644
index 0000000..78faadb
--- /dev/null
+++ b/designPattern/src/com/leosanqing/interpreter/RepeatCommandNode.java
@@ -0,0 +1,23 @@
+package com.leosanqing.interpreter;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 15:00
+ */
+public class RepeatCommandNode extends Node {
+ private int number;
+ private Node commandListNode;
+
+ @Override
+ public void parse(Context context) throws ParseException {
+ context.skipToken("repeat");
+ number = context.currentNumber();
+ context.nextToken();
+ commandListNode = new CommandListNode();
+ commandListNode.parse(context);
+ }
+
+ public String toString() {
+ return "[repeat " + number + " " + commandListNode + "]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/iterator/Aggregate.java b/designPattern/src/com/leosanqing/iterator/Aggregate.java
deleted file mode 100644
index a65af7f..0000000
--- a/designPattern/src/com/leosanqing/iterator/Aggregate.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.leosanqing.iterator;
-
-// Aggregate 接口
-public interface Aggregate {
- public abstract Iterator iterator();
-}
diff --git a/designPattern/src/com/leosanqing/iterator/Book.java b/designPattern/src/com/leosanqing/iterator/Book.java
deleted file mode 100644
index ecd41da..0000000
--- a/designPattern/src/com/leosanqing/iterator/Book.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.leosanqing.iterator;
-
-
-public class Book {
- public String name;
-
- public Book(String name) {
- this.name = name;
- }
-
- public Book() {
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-}
diff --git a/designPattern/src/com/leosanqing/iterator/BookShelf.java b/designPattern/src/com/leosanqing/iterator/BookShelf.java
deleted file mode 100644
index 9a2a576..0000000
--- a/designPattern/src/com/leosanqing/iterator/BookShelf.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.leosanqing.iterator;
-
-public class BookShelf implements Aggregate{
- public Book[] books;
- public int last = 0;
- public BookShelf(int maxsize){
- this.books = new Book[maxsize];
- }
-
- public void appendBook(Book book){
- this.books[last] = book;
- last++;
- }
-
- public Book getBookAt(int index){
- return this.books[index];
- }
- @Override
- public Iterator iterator() {
- return new BookShelfIterator(this);
- }
-
- public int getLength() {
- return last;
- }
-}
diff --git a/designPattern/src/com/leosanqing/iterator/BookShelfIterator.java b/designPattern/src/com/leosanqing/iterator/BookShelfIterator.java
deleted file mode 100644
index 9b37640..0000000
--- a/designPattern/src/com/leosanqing/iterator/BookShelfIterator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.leosanqing.iterator;
-
-public class BookShelfIterator implements Iterator{
- private BookShelf bookShelf;
- private int index;
- public BookShelfIterator(BookShelf bookShelf){
- this.bookShelf = bookShelf ;
- this.index = 0;
- }
-
- @Override
- public boolean hasNext() {
- if(index < bookShelf.getLength()){
- return true;
- }else {
- return false;
- }
- }
-
- @Override
- public Object next() {
- Book book = bookShelf.getBookAt(index);
- index++;
-
- return book;
- }
-}
diff --git a/designPattern/src/com/leosanqing/iterator/Iterator.java b/designPattern/src/com/leosanqing/iterator/Iterator.java
deleted file mode 100644
index 204b5a0..0000000
--- a/designPattern/src/com/leosanqing/iterator/Iterator.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.leosanqing.iterator;
-
-
-// Iterator 是一个接口,里面定义了我们需要的两个方法,
-public interface Iterator {
- public abstract boolean hasNext();
- public abstract Object next();
-}
diff --git a/designPattern/src/com/leosanqing/iterator/Test.java b/designPattern/src/com/leosanqing/iterator/Test.java
deleted file mode 100644
index c4618c8..0000000
--- a/designPattern/src/com/leosanqing/iterator/Test.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.leosanqing.iterator;
-
-import com.leosanqing.iterator.vectorImp.BookShelf;
-
-public class Test {
- public static void main(String[] args) {
-
- BookShelf bookShelf = new BookShelf(5);
- bookShelf.appendBook(new Book("Jobs"));
- bookShelf.appendBook(new Book("Head First Java"));
- bookShelf.appendBook(new Book("Design Pattern"));
-
- Iterator iterator = bookShelf.iterator();
- while (iterator.hasNext()){
- Book next = (Book) iterator.next();
- System.out.println(next.getName());
- }
- }
-}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/Aggregate.java b/designPattern/src/com/leosanqing/iterator/ordinary/Aggregate.java
new file mode 100644
index 0000000..4b90f44
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/Aggregate.java
@@ -0,0 +1,9 @@
+package com.leosanqing.iterator.ordinary;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 16:56
+ */
+public interface Aggregate {
+ Iterator iterator();
+}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/Book.java b/designPattern/src/com/leosanqing/iterator/ordinary/Book.java
new file mode 100644
index 0000000..a011d42
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/Book.java
@@ -0,0 +1,17 @@
+package com.leosanqing.iterator.ordinary;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 16:57
+ */
+public class Book {
+ private String name;
+
+ public Book(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/BookShelf.java b/designPattern/src/com/leosanqing/iterator/ordinary/BookShelf.java
new file mode 100644
index 0000000..c3ffd7f
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/BookShelf.java
@@ -0,0 +1,49 @@
+package com.leosanqing.iterator.ordinary;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 16:57
+ *
+ *
+ * BookShelf 类 实现了 Aggregate 接口。
+ *
+ * Aggregate 接口又使用了 Iterator 接口
+ */
+public class BookShelf implements Aggregate {
+ private Book[] books;
+
+ private int maxSize = 0;
+ private int last = 0;
+
+ public BookShelf(int maxSize) {
+ this.books = new Book[maxSize];
+ this.maxSize = maxSize;
+ }
+
+ public void append(Book book) {
+ if (last > maxSize) {
+ throw new IndexOutOfBoundsException("超过了数组的范围");
+ }
+ books[last] = book;
+ last++;
+ }
+
+ public Book getBookAt(int index) {
+ if (index >= maxSize - 1) {
+ throw new IndexOutOfBoundsException("超过了数组范围: [范围]:"
+ + maxSize + "[index]:" + index);
+ }
+ return books[index];
+ }
+
+ public int getLength(){
+ return last;
+ }
+
+ // 因为 BookShelfIterator 是 Iterator的具体实现
+ // 所以 可以用Iterator 直接接收 返回的BookShelfIterator类型
+ @Override
+ public Iterator iterator() {
+ return new BookShelfIterator(this);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/BookShelfIterator.java b/designPattern/src/com/leosanqing/iterator/ordinary/BookShelfIterator.java
new file mode 100644
index 0000000..d32f4ed
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/BookShelfIterator.java
@@ -0,0 +1,31 @@
+package com.leosanqing.iterator.ordinary;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 17:07
+ *
+ * BookShelfIterator 实现了 Iterator接口。所以他必须实现接口中的两个方法
+ *
+ *
+ */
+public class BookShelfIterator implements Iterator {
+ private BookShelf bookShelf;
+ private int index;
+
+ public BookShelfIterator(BookShelf bookShelf) {
+ this.bookShelf = bookShelf;
+ this.index = 0;
+ }
+
+ @Override
+ public Object next() {
+ Book book = bookShelf.getBookAt(index);
+ index++;
+ return book;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < bookShelf.getLength();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/Iterator.java b/designPattern/src/com/leosanqing/iterator/ordinary/Iterator.java
new file mode 100644
index 0000000..79f4d2b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/Iterator.java
@@ -0,0 +1,10 @@
+package com.leosanqing.iterator.ordinary;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 16:54
+ */
+public interface Iterator {
+ T next();
+ boolean hasNext();
+}
diff --git a/designPattern/src/com/leosanqing/iterator/ordinary/Test.java b/designPattern/src/com/leosanqing/iterator/ordinary/Test.java
new file mode 100644
index 0000000..609410b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/iterator/ordinary/Test.java
@@ -0,0 +1,18 @@
+package com.leosanqing.iterator.ordinary;
+
+
+
+public class Test {
+ public static void main(String[] args) {
+ BookShelf bookShelf = new BookShelf(5);
+ bookShelf.append(new Book("Jobs"));
+ bookShelf.append(new Book("Head First Java"));
+ bookShelf.append(new Book("Design Pattern"));
+
+ Iterator iterator = bookShelf.iterator();
+ while (iterator.hasNext()){
+ Book next = (Book)iterator.next();
+ System.out.println(next.getName());
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelf.java b/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelf.java
index 4bc3531..8206d06 100644
--- a/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelf.java
+++ b/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelf.java
@@ -1,34 +1,33 @@
package com.leosanqing.iterator.vectorImp;
-import com.leosanqing.iterator.Aggregate;
-import com.leosanqing.iterator.Book;
-import com.leosanqing.iterator.Iterator;
+import com.leosanqing.iterator.ordinary.Aggregate;
+import com.leosanqing.iterator.ordinary.Iterator;
import java.util.Vector;
/**
- * 将数组改成 vector,其他不更改,代码仍然可以运行
+ * 将数组改成 vector,其他不更改
+ *
+ * 代码仍然可以运行,并且使用泛型
*/
-public class BookShelf implements Aggregate {
- public Vector books;
- private int last = 0;
+public class BookShelf implements Aggregate {
+ public Vector books;
- public BookShelf(int maxsize){
+ public BookShelf(int maxsize) {
books = new Vector<>(maxsize);
}
- public Book getBookAt(int index){
+ public T getBookAt(int index) {
return books.elementAt(index);
}
- public void appendBook(Book book){
- books.add(last,book);
- last++;
+ public void appendBook(T book) {
+ books.add(book);
}
- public int getLength(){
- return last;
+ public int getLength() {
+ return books.size();
}
@Override
diff --git a/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelfIteratorVec.java b/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelfIteratorVec.java
index 66fd256..263e2de 100644
--- a/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelfIteratorVec.java
+++ b/designPattern/src/com/leosanqing/iterator/vectorImp/BookShelfIteratorVec.java
@@ -1,28 +1,24 @@
package com.leosanqing.iterator.vectorImp;
-import com.leosanqing.iterator.Book;
-import com.leosanqing.iterator.Iterator;
+import com.leosanqing.iterator.ordinary.Iterator;
-public class BookShelfIteratorVec implements Iterator{
- private BookShelf bookShelfVec;
+public class BookShelfIteratorVec implements Iterator {
+ private BookShelf bookShelfVec;
private int index;
- public BookShelfIteratorVec(BookShelf bookShelf){
- this.bookShelfVec = bookShelf ;
+
+ public BookShelfIteratorVec(BookShelf bookShelf) {
+ this.bookShelfVec = bookShelf;
this.index = 0;
}
@Override
public boolean hasNext() {
- if(index < bookShelfVec.getLength()){
- return true;
- }else {
- return false;
- }
+ return index < bookShelfVec.getLength();
}
@Override
- public Object next() {
- Book book = bookShelfVec.getBookAt(index);
+ public T next() {
+ T book = bookShelfVec.getBookAt(index);
index++;
return book;
diff --git a/designPattern/src/com/leosanqing/iterator/vectorImp/TestVec.java b/designPattern/src/com/leosanqing/iterator/vectorImp/TestVec.java
index 20b45e5..d6462e0 100644
--- a/designPattern/src/com/leosanqing/iterator/vectorImp/TestVec.java
+++ b/designPattern/src/com/leosanqing/iterator/vectorImp/TestVec.java
@@ -1,7 +1,8 @@
package com.leosanqing.iterator.vectorImp;
-import com.leosanqing.iterator.Book;
-import com.leosanqing.iterator.Iterator;
+import com.leosanqing.iterator.ordinary.Book;
+import com.leosanqing.iterator.ordinary.Iterator;
+
public class TestVec {
public static void main(String[] args) {
@@ -9,9 +10,9 @@ public static void main(String[] args) {
bookShelf.appendBook(new Book("head first Java"));
bookShelf.appendBook(new Book("Design Pattern"));
bookShelf.appendBook(new Book("Understanding the JVM"));
- Iterator iterator = bookShelf.iterator();
+ Iterator iterator = bookShelf.iterator();
while(iterator.hasNext()){
- Book book = (Book) iterator.next();
+ Book book = iterator.next();
System.out.println(book.getName());
}
diff --git "a/designPattern/src/com/leosanqing/iterator/\344\270\272\344\273\200\344\271\210\350\246\201\347\224\250Iterator.md" "b/designPattern/src/com/leosanqing/iterator/\344\270\272\344\273\200\344\271\210\350\246\201\347\224\250Iterator.md"
index e96e1a9..39bf34f 100644
--- "a/designPattern/src/com/leosanqing/iterator/\344\270\272\344\273\200\344\271\210\350\246\201\347\224\250Iterator.md"
+++ "b/designPattern/src/com/leosanqing/iterator/\344\270\272\344\273\200\344\271\210\350\246\201\347\224\250Iterator.md"
@@ -32,10 +32,6 @@ while (iterator.hasNext()){
```java
package com.leosanqing.iterator.vectorImp;
-import com.leosanqing.iterator.Aggregate;
-import com.leosanqing.iterator.Book;
-import com.leosanqing.iterator.Iterator;
-
import java.util.Vector;
/**
diff --git a/designPattern/src/com/leosanqing/mediator/Colleague.java b/designPattern/src/com/leosanqing/mediator/Colleague.java
new file mode 100644
index 0000000..d3560cc
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/Colleague.java
@@ -0,0 +1,12 @@
+package com.leosanqing.mediator;
+
+import com.leosanqing.memento.game.Memento;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-27 10:40
+ */
+public interface Colleague {
+ void setMediator(Mediator mediator);
+ void setColleagueEnabled(boolean enabled);
+}
diff --git a/designPattern/src/com/leosanqing/mediator/ColleagueButton.java b/designPattern/src/com/leosanqing/mediator/ColleagueButton.java
new file mode 100644
index 0000000..ff203b3
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/ColleagueButton.java
@@ -0,0 +1,27 @@
+package com.leosanqing.mediator;
+
+import java.awt.*;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-27 10:42
+ */
+public class ColleagueButton extends Button implements Colleague {
+ private Mediator mediator;
+
+ @Override
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+
+ public ColleagueButton(String caption) {
+ super(caption);
+ }
+
+ @Override
+ public void setColleagueEnabled(boolean enabled) {
+ // setEnabled 是Button自己带的方法
+ setEnabled(enabled);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/mediator/ColleagueCheckBox.java b/designPattern/src/com/leosanqing/mediator/ColleagueCheckBox.java
new file mode 100644
index 0000000..47a6ad7
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/ColleagueCheckBox.java
@@ -0,0 +1,32 @@
+package com.leosanqing.mediator;
+
+import java.awt.*;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-28 08:10
+ */
+public class ColleagueCheckBox extends Checkbox implements ItemListener,Colleague {
+ private Mediator mediator;
+
+ public ColleagueCheckBox(String label, CheckboxGroup group, boolean state) throws HeadlessException {
+ super(label, group, state);
+ }
+
+ @Override
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ @Override
+ public void setColleagueEnabled(boolean enabled) {
+ setEnabled(enabled);
+ }
+
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ mediator.colleagueChanged();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/mediator/ColleagueTextField.java b/designPattern/src/com/leosanqing/mediator/ColleagueTextField.java
new file mode 100644
index 0000000..677f73d
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/ColleagueTextField.java
@@ -0,0 +1,33 @@
+package com.leosanqing.mediator;
+
+import java.awt.*;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-27 10:51
+ */
+public class ColleagueTextField extends TextField implements TextListener, Colleague {
+ private Mediator mediator;
+
+ @Override
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ public ColleagueTextField(String text, int columns) {
+ super(text, columns);
+ }
+
+ @Override
+ public void setColleagueEnabled(boolean enabled) {
+ setEnabled(enabled);
+ setBackground(enabled ? Color.white : Color.lightGray);
+ }
+
+ @Override
+ public void textValueChanged(TextEvent e) {
+ mediator.colleagueChanged();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/mediator/LoginFrame.java b/designPattern/src/com/leosanqing/mediator/LoginFrame.java
new file mode 100644
index 0000000..30aa7d6
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/LoginFrame.java
@@ -0,0 +1,100 @@
+package com.leosanqing.mediator;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-28 08:14
+ */
+public class LoginFrame extends Frame implements ActionListener, Mediator {
+ private ColleagueCheckBox checkGuest;
+ private ColleagueCheckBox checkLogin;
+ private ColleagueTextField textUser;
+ private ColleagueTextField textPassword;
+ private ColleagueButton buttonOk;
+ private ColleagueButton buttonCancel;
+
+ public LoginFrame(String title) {
+ super(title);
+ setBackground(Color.LIGHT_GRAY);
+ setLayout(new GridLayout(4, 2));
+ createColleagues();
+
+ add(checkGuest);
+ add(checkLogin);
+ add(new Label("username"));
+ add(textUser);
+ add(new Label("Password"));
+ add(textPassword);
+ add(buttonOk);
+ add(buttonCancel);
+
+ colleagueChanged();
+ pack();
+ setVisible(true);
+ }
+
+
+ // 生成各个Colleague
+ @Override
+ public void createColleagues() {
+ CheckboxGroup g = new CheckboxGroup();
+ checkGuest = new ColleagueCheckBox("Guest",g,true);
+ checkLogin = new ColleagueCheckBox("Login",g,false);
+ textUser = new ColleagueTextField("",10);
+ textPassword = new ColleagueTextField("",10);
+ textPassword.setEchoChar('*');
+ buttonOk = new ColleagueButton("OK");
+ buttonCancel = new ColleagueButton("Cancel");
+
+ // 设置Mediator
+ checkGuest.setMediator(this);
+ checkLogin.setMediator(this);
+ textPassword.setMediator(this);
+ textUser.setMediator(this);
+ buttonOk.setMediator(this);
+ buttonCancel.setMediator(this);
+
+ // 设置Listener
+ checkGuest.addItemListener(checkGuest);
+ checkLogin.addItemListener(checkLogin);
+ textUser.addTextListener(textUser);
+ textPassword.addTextListener(textPassword);
+ buttonOk.addActionListener(this);
+ buttonCancel.addActionListener(this);
+ }
+
+ @Override
+ public void colleagueChanged() {
+ if(checkGuest.getState()){
+ textUser.setColleagueEnabled(false);
+ textPassword.setColleagueEnabled(false);
+ buttonOk.setColleagueEnabled(true);
+ }else{
+ textUser.setColleagueEnabled(true);
+ userPasswordChanged();
+ }
+ }
+
+ private void userPasswordChanged() {
+ if(textUser.getText().length()>0){
+ textPassword.setColleagueEnabled(true);
+ if(textPassword.getText().length()>0){
+ buttonOk.setColleagueEnabled(true);
+ }else {
+ buttonOk.setColleagueEnabled(false);
+ }
+ }else{
+ textPassword.setColleagueEnabled(false);
+ buttonOk.setColleagueEnabled(false);
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e.toString());
+ System.exit(0);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/mediator/Main.java b/designPattern/src/com/leosanqing/mediator/Main.java
new file mode 100644
index 0000000..e4d1137
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/Main.java
@@ -0,0 +1,11 @@
+package com.leosanqing.mediator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-17 22:34
+ */
+public class Main {
+ public static void main(String[] args) {
+ new LoginFrame("Mediator Sample");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/mediator/Mediator.java b/designPattern/src/com/leosanqing/mediator/Mediator.java
new file mode 100644
index 0000000..ae1b7dc
--- /dev/null
+++ b/designPattern/src/com/leosanqing/mediator/Mediator.java
@@ -0,0 +1,10 @@
+package com.leosanqing.mediator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-27 10:38
+ */
+public interface Mediator {
+ void createColleagues();
+ void colleagueChanged();
+}
diff --git a/designPattern/src/com/leosanqing/memento/Main.java b/designPattern/src/com/leosanqing/memento/Main.java
new file mode 100644
index 0000000..22239d8
--- /dev/null
+++ b/designPattern/src/com/leosanqing/memento/Main.java
@@ -0,0 +1,39 @@
+package com.leosanqing.memento;
+
+import com.leosanqing.memento.game.Gamer;
+import com.leosanqing.memento.game.Memento;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 08:23
+ */
+public class Main {
+ public static void main(String[] args) {
+ Gamer gamer = new Gamer(100);
+ Memento memento = gamer.createMemento();
+ for (int i = 0; i < 100; i++) {
+ System.out.println("===== "+i);
+ System.out.println("当前状态: "+ gamer);
+
+ gamer.bet();
+
+ System.out.println("所持金钱数为"+gamer.getMoney()+"元");
+
+ // 如何处理Memento
+ if(gamer.getMoney() > memento.getMoney()){
+ System.out.println(" (金钱数增加了,因此保存当前状态)");
+ memento = gamer.createMemento();
+ }else if(gamer.getMoney() < memento.getMoney()/2){
+ System.out.println(" (金钱数减少了,因此将游戏恢复至以前的状态)");
+ gamer.restoreMemento(memento);
+ }
+
+
+ try {
+ Thread.sleep(1100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/memento/game/Gamer.java b/designPattern/src/com/leosanqing/memento/game/Gamer.java
new file mode 100644
index 0000000..68d359c
--- /dev/null
+++ b/designPattern/src/com/leosanqing/memento/game/Gamer.java
@@ -0,0 +1,71 @@
+package com.leosanqing.memento.game;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 07:50
+ */
+public class Gamer {
+ private int money;
+ private List fruits = new ArrayList<>();
+ private Random random = new Random();
+ private static String[] fruitsName = {
+ "苹果", "香蕉", "椰子", "橘子"
+ };
+
+ public Gamer(int money) {
+ this.money = money;
+ }
+
+ public int getMoney() {
+ return money;
+ }
+
+ public void bet() {
+ int dice = random.nextInt(6) + 1;
+
+ if (dice == 1) {
+ money += 100;
+ } else if (dice == 2) {
+ money /= 2;
+ } else if (dice == 6) {
+ String fruit = getFruit();
+ System.out.println(" 获得了水果(" + fruit + ")");
+ fruits.add(fruit);
+ } else {
+ System.out.println("什么也没有发生");
+ }
+ }
+
+
+ public Memento createMemento() {
+ Memento memento = new Memento(money);
+ for (String fruit : fruits) {
+ if (fruit.startsWith("好吃的")) {
+ memento.addFruit(fruit);
+ }
+ }
+ return memento;
+ }
+
+ private String getFruit() {
+ String prefix = "";
+ if (random.nextBoolean()) {
+ prefix = "好吃的";
+ }
+ return prefix + fruitsName[random.nextInt(fruitsName.length)];
+ }
+
+ @Override
+ public String toString() {
+ return "[money = " + money + ",fruit = " + fruits + "]";
+ }
+
+ public void restoreMemento(Memento memento) {
+ this.money = memento.money;
+ this.fruits = memento.getFruits();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/memento/game/Memento.java b/designPattern/src/com/leosanqing/memento/game/Memento.java
new file mode 100644
index 0000000..eafe632
--- /dev/null
+++ b/designPattern/src/com/leosanqing/memento/game/Memento.java
@@ -0,0 +1,30 @@
+package com.leosanqing.memento.game;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 07:43
+ */
+public class Memento {
+ int money;
+ ArrayList fruits ;
+ public int getMoney(){
+ return money;
+ }
+
+ Memento(int money){
+ this.money = money;
+ this.fruits = new ArrayList<>();
+ }
+
+ void addFruit(String fruit){
+ fruits.add(fruit);
+ }
+
+ List getFruits(){
+ List clone = (List) fruits.clone();
+ return clone;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/DigitObserver.java b/designPattern/src/com/leosanqing/observer/DigitObserver.java
new file mode 100644
index 0000000..eab7d19
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/DigitObserver.java
@@ -0,0 +1,17 @@
+package com.leosanqing.observer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 08:01
+ */
+public class DigitObserver implements Observer {
+ @Override
+ public void update(NumberGenerator numberGenerator) {
+ System.out.println("DigitObserver:" + numberGenerator.getNumber());
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/GraphObserver.java b/designPattern/src/com/leosanqing/observer/GraphObserver.java
new file mode 100644
index 0000000..2a6ad8c
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/GraphObserver.java
@@ -0,0 +1,22 @@
+package com.leosanqing.observer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 08:03
+ */
+public class GraphObserver implements Observer{
+
+ @Override
+ public void update(NumberGenerator numberGenerator) {
+ System.out.print("GraphObserver: ");
+ for (int i = 0; i < numberGenerator.getNumber(); i++) {
+ System.out.print("*");
+ }
+ System.out.println();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/Main.java b/designPattern/src/com/leosanqing/observer/Main.java
new file mode 100644
index 0000000..7b79600
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/Main.java
@@ -0,0 +1,16 @@
+package com.leosanqing.observer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-18 22:36
+ */
+public class Main {
+ public static void main(String[] args) {
+ NumberGenerator generator = new RandomNumberGenerator<>();
+ Observer digitObserver = new DigitObserver();
+ Observer graphObserver = new GraphObserver();
+ generator.addObserver(digitObserver);
+ generator.addObserver(graphObserver);
+ generator.execute();
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/NumberGenerator.java b/designPattern/src/com/leosanqing/observer/NumberGenerator.java
new file mode 100644
index 0000000..1debee8
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/NumberGenerator.java
@@ -0,0 +1,55 @@
+package com.leosanqing.observer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 07:48
+ */
+public abstract class NumberGenerator {
+ private ArrayList observers = new ArrayList();
+ public void addObserver(T observer){
+ observers.add(observer);
+ }
+
+ public void deleteObserver(T observer){
+ observers.remove(observer);
+ }
+
+ /**
+ * 发送通知
+ */
+ public void notifyObservers(){
+ Iterator iterator = observers.iterator();
+ while(iterator.hasNext()){
+ T next = (T)iterator.next();
+ next.update(this);
+ }
+ }
+
+
+ /**
+ * 使用更简单的 foreach
+ */
+ public void notifyObservers1(){
+ for (T observer : observers) {
+ observer.update(this);
+ }
+
+ }
+
+ /**
+ * 获取数值
+ * @return
+ */
+ public abstract int getNumber();
+
+ /**
+ * 生成数值
+ */
+ public abstract void execute();
+
+
+
+}
diff --git a/designPattern/src/com/leosanqing/observer/Observer.java b/designPattern/src/com/leosanqing/observer/Observer.java
new file mode 100644
index 0000000..b7cb76b
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/Observer.java
@@ -0,0 +1,13 @@
+package com.leosanqing.observer;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 07:48
+ */
+public interface Observer {
+ /**
+ * 更新数值
+ * @param numberGenerator
+ */
+ void update(NumberGenerator numberGenerator);
+}
diff --git a/designPattern/src/com/leosanqing/observer/RandomNumberGenerator.java b/designPattern/src/com/leosanqing/observer/RandomNumberGenerator.java
new file mode 100644
index 0000000..b8e44ba
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/RandomNumberGenerator.java
@@ -0,0 +1,24 @@
+package com.leosanqing.observer;
+
+import java.util.Random;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 08:00
+ */
+public class RandomNumberGenerator extends NumberGenerator {
+ private Random random = new Random();
+ private int number;
+ @Override
+ public int getNumber() {
+ return number;
+ }
+
+ @Override
+ public void execute() {
+ for (int i = 0; i < 20; i++) {
+ number = random.nextInt(50);
+ notifyObservers();
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/callback/ICallBack.java b/designPattern/src/com/leosanqing/observer/callback/ICallBack.java
new file mode 100644
index 0000000..5e0fdc5
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/callback/ICallBack.java
@@ -0,0 +1,9 @@
+package com.leosanqing.observer.callback;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 22:37
+ */
+public interface ICallBack {
+ void setResult(String string);
+}
diff --git a/designPattern/src/com/leosanqing/observer/callback/Main.java b/designPattern/src/com/leosanqing/observer/callback/Main.java
new file mode 100644
index 0000000..8b0f34c
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/callback/Main.java
@@ -0,0 +1,20 @@
+package com.leosanqing.observer.callback;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 22:47
+ */
+public class Main {
+ public static void main(String[] args) {
+ MomCallbackImpl momCallback = new MomCallbackImpl();
+ XiaoMing xiaoMing = new XiaoMing();
+ momCallback.say(xiaoMing,"小明,去叫你爸爸吃饭");
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ xiaoMing.workDown("爸爸叫回来了");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/observer/callback/MomCallbackImpl.java b/designPattern/src/com/leosanqing/observer/callback/MomCallbackImpl.java
new file mode 100644
index 0000000..bd4b6e9
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/callback/MomCallbackImpl.java
@@ -0,0 +1,24 @@
+package com.leosanqing.observer.callback;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 22:40
+ */
+public class MomCallbackImpl implements ICallBack {
+
+
+ public void say(XiaoMing xiaoMing,String string){
+ xiaoMing.work(this,string);
+ }
+
+ @Override
+ public void setResult(String string) {
+ System.out.println(string);
+ eat();
+ }
+
+ private void eat() {
+ System.out.println("好了,那就准备吃饭吧");
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/observer/callback/XiaoMing.java b/designPattern/src/com/leosanqing/observer/callback/XiaoMing.java
new file mode 100644
index 0000000..ebdd793
--- /dev/null
+++ b/designPattern/src/com/leosanqing/observer/callback/XiaoMing.java
@@ -0,0 +1,23 @@
+package com.leosanqing.observer.callback;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-29 22:37
+ */
+public class XiaoMing {
+ private ICallBack iCallBack;
+
+
+ public void work(ICallBack iCallBack,String string) {
+ this.iCallBack = iCallBack;
+ System.out.println(string);
+ System.out.println("收到了,马上去");
+ }
+
+
+ public void workDown(String string){
+ if(iCallBack!=null){
+ iCallBack.setResult(string);
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/prototype/MessageBox.java b/designPattern/src/com/leosanqing/prototype/MessageBox.java
index 77b5a31..d4eac9e 100644
--- a/designPattern/src/com/leosanqing/prototype/MessageBox.java
+++ b/designPattern/src/com/leosanqing/prototype/MessageBox.java
@@ -4,7 +4,7 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-02 07:09
+ * @Date: 2019-09-23 07:09
*/
public class MessageBox implements Product {
private char c;
@@ -27,6 +27,8 @@ public void use(String s) {
System.out.println();
}
+ // 因为 MessageBox是Product的子类,所以可以强转为Product,
+ // 并在Manager类中使用Product 接收 MessageBox 和UnderlinePane
@Override
public Product createClone() {
Product p = null;
diff --git a/designPattern/src/com/leosanqing/prototype/framework/Manager.java b/designPattern/src/com/leosanqing/prototype/framework/Manager.java
index 26666c7..aea5fd1 100644
--- a/designPattern/src/com/leosanqing/prototype/framework/Manager.java
+++ b/designPattern/src/com/leosanqing/prototype/framework/Manager.java
@@ -6,10 +6,24 @@
* @Author: leosanqing
* @Date: 2019-08-02 07:04
*/
+
+
+/**
+ * 在prototype模式中,我们是根据现有的实例来进行创建新的实例,但我们也没有使用new关键字
+ *
+ * 什么时候用 prototype呢?
+ * 1. 对象种类繁多,不能整合到一个类中
+ * 2.难以根据类生成实例(prototype根据现有类生成实例)
+ * 3.想解耦框架与生成的实例时
+ *
+ *
+ * 类名不一定是束缚,但是如果在代码中使用类名,就无法和该类分离开,无法实现复用
+ */
public class Manager {
- private HashMap showcase = new HashMap<>();
- public void register(String s,Product product){
- showcase.put(s,product);
+ private HashMap showcase = new HashMap<>();
+
+ public void register(String name,Product product){
+ showcase.put(name, product);
}
public Product create(String protoname){
diff --git a/designPattern/src/com/leosanqing/prototype/framework/Product.java b/designPattern/src/com/leosanqing/prototype/framework/Product.java
index f58a52b..ad0719a 100644
--- a/designPattern/src/com/leosanqing/prototype/framework/Product.java
+++ b/designPattern/src/com/leosanqing/prototype/framework/Product.java
@@ -2,9 +2,9 @@
/**
* @Author: leosanqing
- * @Date: 2019-08-02 07:03
+ * @Date: 2019-09-22 21:53
*/
public interface Product extends Cloneable{
- public void use(String s);
- public Product createClone();
+ void use(String s);
+ Product createClone();
}
diff --git a/designPattern/src/com/leosanqing/proxy/Main.java b/designPattern/src/com/leosanqing/proxy/Main.java
new file mode 100644
index 0000000..a043522
--- /dev/null
+++ b/designPattern/src/com/leosanqing/proxy/Main.java
@@ -0,0 +1,17 @@
+package com.leosanqing.proxy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-22 10:04
+ */
+public class Main {
+ public static void main(String[] args) {
+ Printable proxy = new ProxyPrinter("Alice");
+ System.out.println("现在的名字是"+proxy.getPrinterName());
+
+ proxy.setPrinterName("Bob");
+ System.out.println("现在的名字是"+proxy.getPrinterName());
+
+ proxy.print("leosanqing");
+ }
+}
diff --git a/designPattern/src/com/leosanqing/proxy/Printable.java b/designPattern/src/com/leosanqing/proxy/Printable.java
new file mode 100644
index 0000000..6aa9de7
--- /dev/null
+++ b/designPattern/src/com/leosanqing/proxy/Printable.java
@@ -0,0 +1,11 @@
+package com.leosanqing.proxy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-30 23:28
+ */
+public interface Printable {
+ void setPrinterName(String name);
+ void print(String string);
+ String getPrinterName();
+}
diff --git a/designPattern/src/com/leosanqing/proxy/Printer.java b/designPattern/src/com/leosanqing/proxy/Printer.java
new file mode 100644
index 0000000..10bd77d
--- /dev/null
+++ b/designPattern/src/com/leosanqing/proxy/Printer.java
@@ -0,0 +1,51 @@
+package com.leosanqing.proxy;
+
+import com.leosanqing.adapter.trust.Print;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-30 23:30
+ */
+public class Printer implements Printable {
+ private String name;
+
+ public Printer() {
+ heavyJob("正在生成Printer的实例");
+ }
+
+ public Printer(String name) {
+ this.name = name;
+ heavyJob("正在生成Printer的实例(" + name + ")");
+ }
+
+ private void heavyJob(String s) {
+ System.out.println(s);
+ for (int i = 0; i < 5; i++) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.print(".");
+ }
+ System.out.println("finish");
+ }
+
+
+ @Override
+ public void setPrinterName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void print(String string) {
+ System.out.println("===" + name + "===");
+ System.out.println(string);
+
+ }
+
+ @Override
+ public String getPrinterName() {
+ return name;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/proxy/ProxyPrinter.java b/designPattern/src/com/leosanqing/proxy/ProxyPrinter.java
new file mode 100644
index 0000000..f0f10c4
--- /dev/null
+++ b/designPattern/src/com/leosanqing/proxy/ProxyPrinter.java
@@ -0,0 +1,39 @@
+package com.leosanqing.proxy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-30 23:36
+ */
+public class ProxyPrinter implements Printable {
+ private String name;
+ private Printable realPrinter;
+
+ public ProxyPrinter(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public synchronized void setPrinterName(String name) {
+ if (realPrinter != null) {
+ realPrinter.setPrinterName(name);
+ }
+ this.name = name;
+ }
+
+ @Override
+ public void print(String string) {
+ realize();
+ realPrinter.print(string);
+ }
+
+ private void realize() {
+ if (realPrinter == null) {
+ realPrinter = new Printer(name);
+ }
+ }
+
+ @Override
+ public String getPrinterName() {
+ return name;
+ }
+}
diff --git a/designPattern/src/com/leosanqing/state/Context.java b/designPattern/src/com/leosanqing/state/Context.java
new file mode 100644
index 0000000..b0f9c12
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/Context.java
@@ -0,0 +1,12 @@
+package com.leosanqing.state;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 20:55
+ */
+public interface Context {
+ void setClock(int hour);
+ void changeState(State state);
+ void callSecurityCenter(String msg);
+ void recordLog(String msg);
+}
diff --git a/designPattern/src/com/leosanqing/state/DayState.java b/designPattern/src/com/leosanqing/state/DayState.java
new file mode 100644
index 0000000..72f6cca
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/DayState.java
@@ -0,0 +1,50 @@
+package com.leosanqing.state;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 21:23
+ *
+ * 因为每次创建一个实例会浪费很多内存,所以使用单例
+ */
+public class DayState implements State{
+ private static volatile DayState instance = null;
+ private DayState (){}
+
+ public static DayState getInstance(){
+ if(null == instance){
+ synchronized (DayState.class){
+ if(null == instance){
+ instance = new DayState();
+ }
+ }
+ }
+ return instance;
+ }
+ @Override
+ public void doClock(Context context, int hour) {
+ if(hour <= 9 || hour>17){
+ context.changeState(NightState.getInstance());
+ }
+ }
+
+ @Override
+ public void doUse(Context context) {
+ context.recordLog("使用金库(白天)");
+ }
+
+ @Override
+ public void doAlarm(Context context) {
+ context.callSecurityCenter("按下警铃(白天)");
+ }
+
+ @Override
+ public void doPhone(Context context) {
+ context.callSecurityCenter("晚上的通话录音");
+ }
+
+
+ @Override
+ public String toString(){
+ return "[白天]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/state/Main.java b/designPattern/src/com/leosanqing/state/Main.java
new file mode 100644
index 0000000..4d1296e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/Main.java
@@ -0,0 +1,21 @@
+package com.leosanqing.state;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 22:31
+ */
+public class Main {
+ public static void main(String[] args) {
+ SafeFrame frame = new SafeFrame("State Sample");
+ while (true){
+ for (int i = 0; i < 24; i++) {
+ frame.setClock(i);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/designPattern/src/com/leosanqing/state/NightState.java b/designPattern/src/com/leosanqing/state/NightState.java
new file mode 100644
index 0000000..44bc476
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/NightState.java
@@ -0,0 +1,50 @@
+package com.leosanqing.state;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 21:28
+ */
+public class NightState implements State {
+ private static volatile NightState instance = null;
+
+ private NightState() {
+ }
+
+ public static NightState getInstance() {
+ if (null == instance) {
+ synchronized (NightState.class) {
+ if (null == instance) {
+ instance = new NightState();
+ }
+ }
+ }
+ return instance;
+ }
+
+ @Override
+ public void doClock(Context context, int hour) {
+ if (hour > 9 && hour <= 17) {
+ context.changeState(DayState.getInstance());
+ }
+ }
+
+ @Override
+ public void doUse(Context context) {
+ context.callSecurityCenter("紧急:晚上使用金库!");
+ }
+
+ @Override
+ public void doAlarm(Context context) {
+ context.callSecurityCenter("按下警铃(晚上)");
+ }
+
+ @Override
+ public void doPhone(Context context) {
+ context.recordLog("晚上的通话录音");
+ }
+
+ @Override
+ public String toString(){
+ return "[晚上]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/state/SafeFrame.java b/designPattern/src/com/leosanqing/state/SafeFrame.java
new file mode 100644
index 0000000..83f347c
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/SafeFrame.java
@@ -0,0 +1,102 @@
+package com.leosanqing.state;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 21:51
+ */
+public class SafeFrame extends Frame implements ActionListener, Context {
+ private TextField textClock = new TextField(60);
+ private TextArea textScreen = new TextArea(10, 60);
+ private Button buttonUse = new Button("使用金库");
+ private Button buttonAlarm = new Button("按下警铃");
+ private Button buttonPhone = new Button("正常通话");
+ private Button buttonExit = new Button("结束");
+
+ private State state = DayState.getInstance();
+
+ public SafeFrame(String title) {
+ super(title);
+ setBackground(Color.lightGray);
+ setLayout(new BorderLayout());
+
+ // 配置textClock
+ add(textClock, BorderLayout.NORTH);
+ textClock.setEditable(false);
+
+ // 配置textScreen
+ add(textScreen, BorderLayout.CENTER);
+ textScreen.setEditable(false);
+ // 为界面添加按钮
+
+ Panel panel = new Panel();
+ panel.add(buttonUse);
+ panel.add(buttonAlarm);
+ panel.add(buttonPhone);
+ panel.add(buttonExit);
+
+ // 配置界面
+ add(panel, BorderLayout.SOUTH);
+
+ // 显示
+ pack();
+ setVisible(true);
+
+ buttonUse.addActionListener(this);
+ buttonAlarm.addActionListener(this);
+ buttonPhone.addActionListener(this);
+ buttonExit.addActionListener(this);
+ }
+
+
+ @Override
+ public void setClock(int hour) {
+ String clockString = "现在时间是:";
+ if (hour < 10) {
+ clockString += "0" + hour + ":00";
+ } else {
+ clockString += hour + ":00";
+ }
+
+ System.out.println(clockString);
+ textClock.setText(clockString);
+ state.doClock(this, hour);
+ }
+
+ @Override
+ public void changeState(State state) {
+ System.out.println("从" + this.state + "状态变为了" + state + "状态");
+ this.state = state;
+ }
+
+ @Override
+ public void callSecurityCenter(String msg) {
+ textScreen.append("call!" + msg + "\n");
+ }
+
+ @Override
+ public void recordLog(String msg) {
+ textScreen.append("record ..."+msg +"\n");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e.toString());
+ if (e.getSource() == buttonUse) {
+ state.doUse(this);
+ } else if (e.getSource() == buttonPhone) {
+ state.doPhone(this);
+ } else if (e.getSource() == buttonAlarm) {
+ state.doAlarm(this);
+ } else if (e.getSource() == buttonExit) {
+ System.exit(0);
+ } else {
+ System.out.println("?");
+ }
+ }
+
+
+}
diff --git a/designPattern/src/com/leosanqing/state/State.java b/designPattern/src/com/leosanqing/state/State.java
new file mode 100644
index 0000000..29ca78f
--- /dev/null
+++ b/designPattern/src/com/leosanqing/state/State.java
@@ -0,0 +1,12 @@
+package com.leosanqing.state;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-19 20:54
+ */
+public interface State {
+ void doClock(Context context,int hour);
+ void doUse(Context context);
+ void doAlarm(Context context);
+ void doPhone(Context context);
+}
diff --git a/designPattern/src/com/leosanqing/strategy/Hand.java b/designPattern/src/com/leosanqing/strategy/Hand.java
new file mode 100644
index 0000000..d37610f
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/Hand.java
@@ -0,0 +1,57 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 09:38
+ *
+ * 这里使用了单例模式,看出来了吗?
+ */
+public class Hand {
+ public static final int HANDVALUE_GUU = 0;
+ public static final int HANDVALUE_CHO = 1;
+ public static final int HANDVALUE_PAA = 2;
+ public static final Hand[] hand = {
+ new Hand(HANDVALUE_GUU),
+ new Hand(HANDVALUE_CHO),
+ new Hand(HANDVALUE_PAA)
+ };
+
+
+ public static final String name[] = {
+ "石头","剪刀","布"
+ };
+ private int handValue;
+
+ private Hand(int handValue) {
+ this.handValue = handValue;
+ }
+
+ public static Hand getHand(int handValue) {
+ return hand[handValue];
+ }
+
+ public boolean isStrongerThan(Hand hand) {
+ return fight(hand) == 1;
+ }
+
+ public boolean isWeakerThan(Hand hand) {
+ return fight(hand) == -1;
+ }
+
+ private int fight(Hand hand) {
+ // 因为是单例,在这里可以放心使用 ==,直接比较二者地址
+ if(this == hand){
+ return 0;
+ }else if((this.handValue +1)%3 == hand.handValue){
+ return 1;
+ }else {
+ return -1;
+ }
+ }
+
+
+ public String toString(){
+ return name[handValue];
+ }
+
+}
diff --git a/designPattern/src/com/leosanqing/strategy/Main.java b/designPattern/src/com/leosanqing/strategy/Main.java
new file mode 100644
index 0000000..203249e
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/Main.java
@@ -0,0 +1,13 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 10:17
+ */
+public class Main {
+ public static void main(String[] args) {
+ Player leosanqing = new Player("leosanqing", new WinningStrategy());
+ Player pipi = new Player("pipi", new ProbStrategy());
+
+ }
+}
diff --git a/designPattern/src/com/leosanqing/strategy/Player.java b/designPattern/src/com/leosanqing/strategy/Player.java
new file mode 100644
index 0000000..a88fab3
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/Player.java
@@ -0,0 +1,44 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 10:07
+ */
+public class Player {
+ private String name;
+ private Strategy strategy;
+ private int winCount;
+ private int loseCount;
+ private int gameCount;
+
+ public Player(String name, Strategy strategy) {
+ this.name = name;
+ this.strategy = strategy;
+ }
+
+ public Hand nextHand() {
+ return strategy.nextHand();
+ }
+
+ public void win() {
+ strategy.study(true);
+ winCount++;
+ gameCount++;
+ }
+
+ public void lose() {
+ strategy.study(false);
+ loseCount++;
+ gameCount++;
+ }
+
+ public void even() {
+ strategy.study(false);
+ gameCount++;
+ }
+
+ public String toString() {
+ return "[" + name + ":" + gameCount + " games, "
+ + winCount + " win, " + loseCount + " lose" + "]";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/strategy/ProbStrategy.java b/designPattern/src/com/leosanqing/strategy/ProbStrategy.java
new file mode 100644
index 0000000..a5277ff
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/ProbStrategy.java
@@ -0,0 +1,17 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 10:06
+ */
+public class ProbStrategy implements Strategy {
+ @Override
+ public Hand nextHand() {
+ return null;
+ }
+
+ @Override
+ public void study(boolean bool) {
+
+ }
+}
diff --git a/designPattern/src/com/leosanqing/strategy/Strategy.java b/designPattern/src/com/leosanqing/strategy/Strategy.java
new file mode 100644
index 0000000..46dceaa
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/Strategy.java
@@ -0,0 +1,10 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 09:37
+ */
+public interface Strategy {
+ Hand nextHand();
+ void study(boolean bool);
+}
diff --git a/designPattern/src/com/leosanqing/strategy/WinningStrategy.java b/designPattern/src/com/leosanqing/strategy/WinningStrategy.java
new file mode 100644
index 0000000..1489d6c
--- /dev/null
+++ b/designPattern/src/com/leosanqing/strategy/WinningStrategy.java
@@ -0,0 +1,18 @@
+package com.leosanqing.strategy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 10:05
+ */
+public class WinningStrategy implements Strategy {
+
+ @Override
+ public Hand nextHand() {
+ return null;
+ }
+
+ @Override
+ public void study(boolean bool) {
+
+ }
+}
diff --git a/designPattern/src/com/leosanqing/template/AbstractDisplay.java b/designPattern/src/com/leosanqing/template/AbstractDisplay.java
index b60b0dd..b0cf669 100644
--- a/designPattern/src/com/leosanqing/template/AbstractDisplay.java
+++ b/designPattern/src/com/leosanqing/template/AbstractDisplay.java
@@ -1,11 +1,22 @@
package com.leosanqing.template;
+
+/**
+ * 父类中定义后续的逻辑,并给出子类需要重写的方法。
+ *
+ * 子类根据父类中定义的函数,实现自己需要的逻辑。
+ *
+ * 请一定要弄清楚这个模式,因为后面的模式中会大量用到这个模式
+ */
public abstract class AbstractDisplay {
public abstract void open();
+
public abstract void print();
+
public abstract void close();
- public final void display(){
+ // 为了不让子类重写父类的这个方法
+ public final void display() {
open();
for (int i = 0; i < 5; i++) {
print();
diff --git a/designPattern/src/com/leosanqing/template/CharDisplay.java b/designPattern/src/com/leosanqing/template/CharDisplay.java
index 355b5fd..20fa948 100644
--- a/designPattern/src/com/leosanqing/template/CharDisplay.java
+++ b/designPattern/src/com/leosanqing/template/CharDisplay.java
@@ -1,10 +1,12 @@
package com.leosanqing.template;
-public class CharDisplay extends AbstractDisplay {
- char ch ;
- public CharDisplay(char ch){
+public class CharDisplay extends AbstractDisplay {
+ private char ch;
+
+ public CharDisplay(char ch) {
this.ch = ch;
}
+
@Override
public void open() {
System.out.print("<<");
diff --git a/designPattern/src/com/leosanqing/template/StringDisplay.java b/designPattern/src/com/leosanqing/template/StringDisplay.java
index 11331c2..b3dda2f 100644
--- a/designPattern/src/com/leosanqing/template/StringDisplay.java
+++ b/designPattern/src/com/leosanqing/template/StringDisplay.java
@@ -1,9 +1,10 @@
package com.leosanqing.template;
public class StringDisplay extends AbstractDisplay {
- private String string;
+ private String string;
private int width;
- public StringDisplay(String string){
+
+ public StringDisplay(String string) {
this.string = string;
this.width = string.getBytes().length;
}
@@ -18,7 +19,7 @@ public void open() {
@Override
public void print() {
- System.out.println("|"+string+"|");
+ System.out.println("|" + string + "|");
}
@Override
@@ -28,7 +29,7 @@ public void close() {
System.out.println("+");
}
- private void printLine(int width){
+ private void printLine(int width) {
for (int i = 0; i < width; i++) {
System.out.print("-");
}
diff --git a/designPattern/src/com/leosanqing/visitor/Directory.java b/designPattern/src/com/leosanqing/visitor/Directory.java
new file mode 100644
index 0000000..165c066
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/Directory.java
@@ -0,0 +1,47 @@
+package com.leosanqing.visitor;
+
+import com.leosanqing.factory.idcard.IDCard;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-25 08:23
+ */
+public class Directory extends Entry{
+ private String name;
+
+ private ArrayList directory = new ArrayList<>();
+ public Directory(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public Entry add(Entry entry){
+ directory.add(entry);
+ return entry;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getSize() {
+ int size = 0;
+ for (Entry entry : directory) {
+ size += entry.getSize();
+ }
+ return size;
+ }
+
+
+ public Iterator iterator(){
+ return directory.iterator();
+ }
+ @Override
+ public void accept(Visitor visitor) {
+ visitor.visitor(this);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/Element.java b/designPattern/src/com/leosanqing/visitor/Element.java
new file mode 100644
index 0000000..d969bdb
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/Element.java
@@ -0,0 +1,9 @@
+package com.leosanqing.visitor;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-25 08:26
+ */
+public interface Element {
+ void accept(Visitor visitor);
+}
diff --git a/designPattern/src/com/leosanqing/visitor/Entry.java b/designPattern/src/com/leosanqing/visitor/Entry.java
new file mode 100644
index 0000000..35ef148
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/Entry.java
@@ -0,0 +1,26 @@
+package com.leosanqing.visitor;
+
+
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-25 08:12
+ */
+public abstract class Entry implements Element{
+ public abstract String getName();
+
+ public abstract int getSize();
+
+ public Entry add(Entry entry) throws FileTreatmentException {
+ throw new FileTreatmentException();
+ }
+
+ public Iterator iterator() throws FileTreatmentException {
+ throw new FileTreatmentException();
+ }
+
+ public String toString() {
+ return getName() + "(" + getSize() + ")";
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/File.java b/designPattern/src/com/leosanqing/visitor/File.java
new file mode 100644
index 0000000..4f64019
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/File.java
@@ -0,0 +1,30 @@
+package com.leosanqing.visitor;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-25 08:15
+ */
+public class File extends Entry{
+ private String name;
+ private int size;
+
+ public File(String name, int size) {
+ this.name = name;
+ this.size = size;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getSize() {
+ return size;
+ }
+
+ @Override
+ public void accept(Visitor visitor) {
+ visitor.visitor(this);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/FileTreatmentException.java b/designPattern/src/com/leosanqing/visitor/FileTreatmentException.java
new file mode 100644
index 0000000..1e19abd
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/FileTreatmentException.java
@@ -0,0 +1,15 @@
+package com.leosanqing.visitor;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-25 08:14
+ */
+public class FileTreatmentException extends Exception {
+ public FileTreatmentException(){
+
+ }
+
+ public FileTreatmentException(String msg){
+ super(msg);
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/ListVisitor.java b/designPattern/src/com/leosanqing/visitor/ListVisitor.java
new file mode 100644
index 0000000..77c45f5
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/ListVisitor.java
@@ -0,0 +1,33 @@
+package com.leosanqing.visitor;
+
+import java.util.Iterator;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-10-22 07:58
+ */
+public class ListVisitor extends Visitor {
+ private String currentDir = "";
+
+ @Override
+ public void visitor(File file) {
+ System.out.println(currentDir + "/" + file);
+ }
+
+ @Override
+ public void visitor(Directory directory) {
+ System.out.println(currentDir + "/" + directory);
+ String saveDir = currentDir;
+ currentDir = currentDir + "/" + directory.getName();
+
+ Iterator iterator = directory.iterator();
+
+ while (iterator.hasNext()){
+ Entry entry = iterator.next();
+ entry.accept(this);
+ }
+
+ currentDir = saveDir;
+
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/Main.java b/designPattern/src/com/leosanqing/visitor/Main.java
new file mode 100644
index 0000000..98fb3d5
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/Main.java
@@ -0,0 +1,41 @@
+package com.leosanqing.visitor;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 20:27
+ */
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Making root entries....");
+ Directory root = new Directory("root");
+ Directory usr = new Directory("usr");
+ Directory tmp = new Directory("tmp");
+ Directory bin = new Directory("bin");
+
+ root.add(usr);
+ root.add(tmp);
+ root.add(bin);
+
+ bin.add(new File("vi",100));
+ bin.add(new File("latex",500));
+
+ root.accept(new ListVisitor());
+
+ System.out.println();
+ System.out.println("Making usr entries");
+
+ Directory leosanqing = new Directory("leosanqing");
+ Directory pipi = new Directory("pipi");
+ Directory leo = new Directory("leo");
+ usr.add(leosanqing);
+ usr.add(pipi);
+ usr.add(leo);
+
+ leosanqing.add(new File("Design Pattern.pdf",1000));
+ leosanqing.add(new File("Understanding The JVM.pdf",2000));
+ pipi.add(new File("First Love.mobi",400));
+ leo.add(new File("XXX.avi",10000));
+
+ root.accept(new ListVisitor());
+ }
+}
diff --git a/designPattern/src/com/leosanqing/visitor/Visitor.java b/designPattern/src/com/leosanqing/visitor/Visitor.java
new file mode 100644
index 0000000..becf960
--- /dev/null
+++ b/designPattern/src/com/leosanqing/visitor/Visitor.java
@@ -0,0 +1,17 @@
+package com.leosanqing.visitor;
+
+
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-09-15 20:06
+ *
+ * 目的: 将处理从数据结构中分离出来
+ *
+ * 好处: 易于增加ConcreteVisitor 角色(就是类似于ListVisitor的了类),
+ * 缺点: 难以增加 Entry 的子类,如果我们增加一个新的类,就要修改Visitor的类
+ */
+public abstract class Visitor {
+ public abstract void visitor(File file);
+ public abstract void visitor(Directory directory);
+}
diff --git a/designPattern/welcome.html b/designPattern/welcome.html
new file mode 100644
index 0000000..1921956
--- /dev/null
+++ b/designPattern/welcome.html
@@ -0,0 +1,4 @@
+Welcome to leosanqing's page
+Welcome to leosanqing's page
+leosanqing欢迎来到leosanqing的主页
等你邮件哦
leosanqing
\ No newline at end of file
diff --git a/img/.DS_Store b/img/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/img/.DS_Store differ
diff --git a/img/IMG_20191120_212413-min.jpg b/img/IMG_20191120_212413-min.jpg
new file mode 100644
index 0000000..39bb358
Binary files /dev/null and b/img/IMG_20191120_212413-min.jpg differ
diff --git a/img/Xnip2020-03-08_21-24-27.jpg b/img/Xnip2020-03-08_21-24-27.jpg
new file mode 100644
index 0000000..a32b6cf
Binary files /dev/null and b/img/Xnip2020-03-08_21-24-27.jpg differ
diff --git a/img/Xnip2020-04-14_17-21-28.jpg b/img/Xnip2020-04-14_17-21-28.jpg
new file mode 100644
index 0000000..1be0b9f
Binary files /dev/null and b/img/Xnip2020-04-14_17-21-28.jpg differ
diff --git a/img/Xnip2020-05-11_14-31-29.jpg b/img/Xnip2020-05-11_14-31-29.jpg
new file mode 100644
index 0000000..2cbbad7
Binary files /dev/null and b/img/Xnip2020-05-11_14-31-29.jpg differ
diff --git a/img/Xnip2020-05-11_14-39-28.jpg b/img/Xnip2020-05-11_14-39-28.jpg
new file mode 100644
index 0000000..f81f855
Binary files /dev/null and b/img/Xnip2020-05-11_14-39-28.jpg differ
diff --git a/java-note-algorithm/.idea/$CACHE_FILE$ b/java-note-algorithm/.idea/$CACHE_FILE$
new file mode 100644
index 0000000..6cb8985
--- /dev/null
+++ b/java-note-algorithm/.idea/$CACHE_FILE$
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/.gitignore b/java-note-algorithm/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/java-note-algorithm/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/java-note-algorithm/.idea/compiler.xml b/java-note-algorithm/.idea/compiler.xml
new file mode 100644
index 0000000..4db2371
--- /dev/null
+++ b/java-note-algorithm/.idea/compiler.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/inspectionProfiles/Project_Default.xml b/java-note-algorithm/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6560a98
--- /dev/null
+++ b/java-note-algorithm/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/jarRepositories.xml b/java-note-algorithm/.idea/jarRepositories.xml
new file mode 100644
index 0000000..32e7c7d
--- /dev/null
+++ b/java-note-algorithm/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/misc.xml b/java-note-algorithm/.idea/misc.xml
new file mode 100644
index 0000000..b49fb2f
--- /dev/null
+++ b/java-note-algorithm/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/uiDesigner.xml b/java-note-algorithm/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/java-note-algorithm/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/.idea/vcs.xml b/java-note-algorithm/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/java-note-algorithm/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/README.md b/java-note-algorithm/README.md
new file mode 100644
index 0000000..2adb555
--- /dev/null
+++ b/java-note-algorithm/README.md
@@ -0,0 +1,74 @@
+# 前言
+
+大家应该都知道算法的重要性,不管是大厂小厂都非常重视,因为这个不仅考察你的逻辑能力,还有对数据结构的了解程度,还有各个集合类是否熟练
+
+这一部分就是 算法的章节。
+
+主要是 **剑指offer** 和 **LeetCode**上面的算法题进行整理
+
+**剑指offer因为是C语言版,这里改成Java版本**
+
+
+
+这两个主要是之前自己刷题的时候写下来的,然后顺便传到GitHub上,对你们可能也有些帮助
+
+
+
+# 先看哪个
+
+**针对不同时间,侧重点也会不同**
+
+- 如果你时间多(离面试还有3月以上)
+ - 刷Leetcode
+- 如果马上就要校招、社招了。刷剑指Offer。
+
+
+
+# 格式
+
+
+
+## 类名
+
+- 题号+类名
+
+## 文档注释
+
+- **主类最上面是整个问题的描述**以及我对这个题目的**审题**和**解题思路**
+- 里面的静态方法是各个**不同的解题的方法**。会有**解题思路**+**时间空间复杂度**
+- 也会有我对这个**现有题目进行拓展**的一些想法和**解题思路**,比如下图所示
+
+针对该题目,进行一些发散性思考。(不一定是最优的,但是思考很重要)
+
+
+
+# 剑指Offer
+
+很多公司,非大厂(大厂自己会改题)都从这个里面找算法题,你会看到很多校招的算法题90%都是在这本书里,所以如果你时间不多,可以突击刷这个
+
+
+
+# LeetCode
+
+分为简单和中等,因为大厂的算法一般也就是中等难度,很多算法都是在中等(算法岗除外)
+
+每个题都是通过了测试,但是代码的风格质量可能不是最优的
+
+总共就一个项目,项目分类按照包分类,分为
+
+- 简单
+ - 数组
+ - 链表
+ - 哈希
+ - 二叉树
+ - 等..
+- 中等
+
+因为题目不可能是孤立的(比如一个题可能同时要用到数组和hash),所以只是大致分了下,我用什么标签搜索的就放进了哪个包
+
+每一个类就是一个题目,每个类中的注释都会有
+
+- 题目描述
+- 示例
+- 思路
+- 代码
\ No newline at end of file
diff --git a/java-note-algorithm/java-note-algorithm.iml b/java-note-algorithm/java-note-algorithm.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/java-note-algorithm/java-note-algorithm.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/pom.xml b/java-note-algorithm/pom.xml
new file mode 100644
index 0000000..ef29ff9
--- /dev/null
+++ b/java-note-algorithm/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ org.example
+ java-note-algorithm
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+ 8
+
+
+
+
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.47
+
+
+ org.projectlombok
+ lombok
+ 1.18.12
+
+
+
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java
new file mode 100644
index 0000000..f86c45f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.easy;
+
+/**
+ * 描述 : 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
+ * 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
+ * 注意你不能在买入股票前卖出股票。
+ *
+ * 示例1: 输入: [7,1,5,3,6,4]
+ * 输出: 5
+ * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
+ * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
+ *
+ * 示例2 输入: [7,6,4,3,1]
+ * 输出: 0
+ * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
+ */
+
+public class _121_BestTimeToBuyAndSellStock {
+
+ /**
+ * 直接暴力求解,遍历两次数组,求出最优解
+ */
+
+ public static int violence(int[] prices) {
+ if (prices == null || prices.length == 0) {
+ return 0;
+ }
+ int maxProfit = 0;
+ for (int i = 0; i < prices.length; i++) {
+ for (int j = i + 1; j < prices.length; j++) {
+ if (prices[j] - prices[i] > maxProfit) {
+ maxProfit = prices[j] - prices[i];
+ }
+
+ }
+ }
+ return maxProfit;
+ }
+
+
+ /**
+ * 动态规划:
+ * 1.定义一个从最开始到当前位置的最小值
+ * 2.计算今天减去最小值的值,也就是当天的利润
+ * 3.比较当天的利润和之前的最大利润
+ */
+ public static int dp(int[] prices) {
+ if (prices == null || prices.length == 0)
+ return 0;
+
+ int minProfit = Integer.MAX_VALUE;
+ int maxProfit = 0;
+
+ for (int price : prices) {
+ //找到最小值
+ minProfit = Math.min(minProfit, price);
+ //比较当天的利润和最大利润
+ maxProfit = Math.max(maxProfit, (price - minProfit));
+ }
+ return maxProfit;
+ }
+
+ public static void main(String[] args) {
+ int[] a = {7, 6, 4, 3, 1};
+ System.out.println(violence(a) == dp(a));
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java
new file mode 100644
index 0000000..7851f2a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java
@@ -0,0 +1,44 @@
+package com.leosanqing.leetcode.easy;
+
+/**
+ * 描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
+ * 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
+ * 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
+ *
+ * 示例1: 输入: [7,1,5,3,6,4]
+ * 输出: 7
+ * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
+ * 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
+ * 示例2: 输入: [1,2,3,4,5]
+ * 输出: 4
+ * 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
+ * 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
+ * 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
+ *
+ * 思路:使用两个变量 一个valley表示当天天数中最低价,
+ * 一个peek表示当前所有的天数中的最高价
+ * 因为我们可以买卖股票且是不用付手续费的,也就是我们可以卖了这一只股票,然后再把它买回来
+ * 所以上面示例2中,5-1和 (2-1)+(3-2)+(4-3)+(5-4)的效果是一样的,所以顶峰就找递增的,底就找递减的
+ */
+public class _122_BestTimeToBuyAndSellStock2 {
+ public int maxProfit(int[] prices) {
+ if (prices == null || prices.length == 0)
+ return 0;
+
+ int valley = prices[0], peek = prices[0];
+ int i = 0;
+ int maxProfit = 0;
+
+ while (i < prices.length - 1) {
+ while (i < prices.length - 1 && prices[i] >= prices[i + 1])
+ i++;
+ valley = prices[i];
+
+ while (i < prices.length - 1 && prices[i] <= prices[i + 1])
+ i++;
+ peek = prices[i];
+ maxProfit += peek - valley;
+ }
+ return maxProfit;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_136_singleNum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_136_singleNum.java
new file mode 100644
index 0000000..858ad1e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_136_singleNum.java
@@ -0,0 +1,33 @@
+package com.leosanqing.leetcode.easy;
+
+/**
+ * 描述:
+ * ` Given a non-empty array of integers, every element appears twice except for one. Find that single one.
+ * ` 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
+ * ` 说明:
+ * ` 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
+ * ` 输入: [4,1,2,1,2]
+ * ` 输出: 4
+ * `
+ * `
+ * ` 思路:使用异或运算:
+ * ` 异或运算有三个特征:
+ * ` 1、0 ^ 任何数都为 那个数 0^a = a;
+ * ` 2、两个相同的数异或结果为 0 a^a = 0;
+ * ` 3、异或具有交换律 a^b^c = a^c^b
+ */
+public class _136_singleNum {
+ public static void main(String[] args) {
+ int[] nums = {4, 2, 1, 2, 1};
+ System.out.println("singleNum(nums) = " + singleNum(nums));
+
+ }
+
+ public static int singleNum(int[] nums) {
+ int result = 0;
+ for (int num : nums) {
+ result ^= num;
+ }
+ return result;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_202_happyNumber.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_202_happyNumber.java
new file mode 100644
index 0000000..54e38af
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_202_happyNumber.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.easy;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2020/4/15 上午10:17
+ * @Package: easy
+ * @Description: leetCode 202题
+ *
+ * ` A happy number is a number defined by the following process:
+ * ` Starting with any positive integer, replace the number by the sum of the squares of
+ * ` its digits,
+ * ` and repeat the process until the number equals 1 (where it will stay),
+ * ` or it loops endlessly in a cycle which does not include 1.
+ * ` Those numbers for which this process ends in 1 are happy numbers.
+ * `
+ * ` Input: 19
+ * ` Output: true
+ * ` Explanation:
+ * ` 1² + 9² = 82
+ * ` 8² + 2² = 68
+ * ` 6² + 8² = 100
+ * ` 1² + 0² + 0² = 1
+ * ` @Version: v1
+ * `
+ * `
+ * ` 思路:
+ * ` 我们看到最后,其实可以猜出来,只有最终变成一位数才有可能达到他的预期,
+ * ` 如果有两位数或者以上,我们肯定是要对他再一次进行运算的,所以我们就一直往下拆数字就行,
+ * ` 但是这里还有个坑,我们怎么让他不会陷入死循环呢?我们要判断他之前是否运算过,因为如果运算过,就会陷入死循环
+ * ` 我们使用 HashSet ,来判断,如果有值,那么这个肯定之前就运算过,就会陷入死循环。不可能是我们想要的 HappyNum
+ */
+public class _202_happyNumber {
+ public static void main(String[] args) {
+
+ _202_happyNumber happyNumber = new _202_happyNumber();
+ for (int i = 0; i < 10000; i++) {
+ happyNumber.isHappy(i);
+ }
+ }
+
+ public boolean isHappy(int n) {
+ int row = n;
+ Set set = new HashSet<>();
+
+ while (n > 1) {
+ int m = 0;
+ // 计算每位的平方的和
+ while (n > 0) {
+ m = m + (n % 10) * (n % 10);
+ n /= 10;
+ }
+ // 之前运算过,不可能是HappyNum,不跳出去就会陷入死循环
+ if (set.contains(m)) {
+ return false;
+ }
+ set.add(m);
+
+ n = m;
+ }
+ System.out.println(row);
+ return true;
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_203_removeLinkedListElements.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_203_removeLinkedListElements.java
new file mode 100644
index 0000000..096a8ff
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_203_removeLinkedListElements.java
@@ -0,0 +1,51 @@
+package com.leosanqing.leetcode.easy;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/1 下午2:11
+ * @Package: easy
+ * @Description: Remove all elements from a linked list of integers that have value val.
+ * 删除链表中与指定值相同的节点
+ *
+ * Example:
+ *
+ * Input: 1->2->6->3->4->5->6, val = 6
+ * Output: 1->2->3->4->5
+ * @Version: 1.0
+ */
+public class _203_removeLinkedListElements {
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 使用一个虚拟的头结点来预防边界异常情况
+ *
+ * 如果
+ * @param head
+ * @param val
+ * @return
+ */
+ public ListNode removeElements(ListNode head, int val) {
+ // 设置一个虚拟的头结点,就把 特殊的边界节点变成了普通的节点
+ ListNode fakeHead = new ListNode(0);
+ fakeHead.next = head;
+ ListNode pre = fakeHead;
+
+
+ while(pre.next != null){
+ // 直接把上一个节点指向 下一个节点,从而跳过当前节点 ,这样就达到了删除的目的 1->2->6->3->4->5->6, val = 6
+ if(val == pre.next.val){
+ pre.next = pre.next.next;
+ }else {
+// if (pre.next.val == val) pre.next = pre.next.next;
+ pre = pre.next;
+ }
+ }
+ return fakeHead.next;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_204_countPrimes.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_204_countPrimes.java
new file mode 100644
index 0000000..d9ef569
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_204_countPrimes.java
@@ -0,0 +1,90 @@
+package com.leosanqing.leetcode.easy;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2020/4/15 上午11:19
+ * @Package: easy
+ * @Description: 统计素数个数
+ * @Version: 1.0
+ *
+ *
+ * 204. Count Primes
+ * Des:
+ * Count the number of prime numbers less than a non-negative number, n.
+ *
+ * Example:
+ *
+ * Input: 10
+ * Output: 4
+ * Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.
+ */
+public class _204_countPrimes {
+ public static void main(String[] args) {
+// System.out.println(new _204_countPrimes().countPrimes(499979));
+ int num = 49997;
+ System.out.println((new _204_countPrimes().countPrimes(num)) == new _204_countPrimes().countPrimesFast(num));
+// System.out.println(new _204_countPrimes().countPrimesFast(499979));
+ }
+//
+
+ /**
+ * 效率太低 O(n²)
+ *
+ * @param n
+ * @return
+ */
+ public int countPrimes(int n) {
+ if (n <= 2) {
+ return 0;
+ }
+
+ if (n == 3) {
+ return 1;
+ }
+
+ boolean flag = false;
+ int num = 2;
+ for (int i = 3; i < n; i++) {
+ flag = false;
+
+ for (int j = 2; j <= i / 2; j++) {
+ if (i % j == 0) {
+ break;
+ }
+ if (j == i / 2) {
+ flag = true;
+ break;
+ }
+ }
+
+ if (flag) {
+ num++;
+ }
+
+ }
+ return num;
+ }
+
+ /**
+ * O(n·log(log(n)))
+ * 我们设置一个 bool 型的 数组,长度为 我们要输入的长度
+ * 从
+ *
+ * @param n
+ * @return
+ */
+ public int countPrimesFast(int n) {
+ boolean[] notPrime = new boolean[n];
+ int count = 0;
+ for (int i = 2; i < n; i++) {
+ if (!notPrime[i]) {
+ count++;
+ for (int j = 2; i * j < n; j++) {
+ notPrime[i * j] = true;
+ }
+ }
+ }
+
+ return count;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_205_isomorphicStrings.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_205_isomorphicStrings.java
new file mode 100644
index 0000000..d2b865e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_205_isomorphicStrings.java
@@ -0,0 +1,121 @@
+package com.leosanqing.leetcode.easy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/1 下午4:14
+ * @Package: com.leosanqing.leetcode.easy
+ * @Description: Given two strings s and t, determine if they are isomorphic.
+ * Two strings are isomorphic if the characters in s can be replaced to get t.
+ * All occurrences of a character must be replaced with another character while preserving the order of characters.
+ * No two characters may map to the same character but a character may map to itself.
+ *
+ * 给定两个字符串s和t,确定它们是否同构。
+ * 如果可以替换s中的字符以获得t,则两个字符串是同构的。
+ * 在保留字符顺序的同时,必须将所有出现的字符替换为另一个字符。
+ * 不能将两个字符映射到同一字符,但是可以将一个字符映射到自身。
+ * @Version: 1.0
+ *
+ *
+ * Example 1:
+ * Input: s = "egg", t = "add"
+ * Output: true
+ *
+ * Example 2:
+ * Input: s = "foo", t = "bar"
+ * Output: false
+ *
+ * Example 3:
+ * Input: s = "paper", t = "title"
+ * Output: true
+ */
+public class _205_isomorphicStrings {
+
+ public static void main(String[] args) {
+ System.out.println(isIsomorphic("aba","baa"));
+ System.out.println(isIsomorphic("paper","tifae"));
+ System.out.println(isIsomorphic("egg","foo"));
+ System.out.println(isIsomorphic("paper","title"));
+
+ }
+
+
+
+ public static boolean isIsomorphic(String s, String t) {
+
+ Map sHashMap = new HashMap<>(256);
+ Map tHashMap = new HashMap<>(256);
+
+ if(s.length() != t.length()){
+ return false;
+ }
+
+ char sChar;
+ char tChar;
+ for (int i = 0; i < s.length(); i++) {
+
+
+ sChar = s.charAt(i);
+ tChar = t.charAt(i);
+ // 如果sMap 中有,但是tMap中 没有,那么肯定就是有问题的
+ // 或者 如果tMap 中有,但是sMap中 没有
+ if((!sHashMap.containsKey(sChar) && tHashMap.containsKey(tChar))
+ || (sHashMap.containsKey(sChar) && !tHashMap.containsKey(tChar))){
+ return false;
+ }
+ if(!sHashMap.containsKey(sChar)){
+ sHashMap.put(sChar,i);
+ }
+
+ if(!tHashMap.containsKey(tChar)){
+ tHashMap.put(tChar,i);
+ }
+
+ if(!sHashMap.get(sChar).equals(tHashMap.get(tChar))){
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * 大佬们的算法,据说时间 3ms,
+ * 这边是使用 数组,
+ * @param sString
+ * @param tString
+ * @return
+ */
+ public boolean isIsomorphic2(String sString, String tString) {
+
+ char[] s = sString.toCharArray();
+ char[] t = tString.toCharArray();
+
+ int length = s.length;
+ if(length != t.length) {
+ return false;
+ }
+
+ char[] sm = new char[256];
+ char[] tm = new char[256];
+
+ for(int i=0; i
+ * Example:
+ *
+ * Input: 1->2->3->4->5->NULL
+ * Output: 5->4->3->2->1->NULL
+ */
+public class _206_reverseLinkedList {
+
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(1);
+ ListNode node2 = new ListNode(2, node1);
+ ListNode node3 = new ListNode(3, node2);
+ ListNode node4 = new ListNode(4, node3);
+ ListNode node5 = new ListNode(5, node4);
+
+ ListNode listNode = reverseList(node5);
+
+ while(listNode!=null){
+ System.out.println(listNode.val);
+ listNode= listNode.next;
+ }
+ }
+
+ public static ListNode reverseList(ListNode head) {
+ ListNode pre = null;
+ while(head != null){
+
+ // 顺序不能反
+ ListNode next = head.next;
+ head.next = pre;
+
+ pre = head;
+ head = next;
+ }
+
+ return pre;
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_237_deleteNodeInLinkedList.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_237_deleteNodeInLinkedList.java
new file mode 100644
index 0000000..8d6ce41
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_237_deleteNodeInLinkedList.java
@@ -0,0 +1,44 @@
+package com.leosanqing.leetcode.easy;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ *` 描述:Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
+ *`
+ *` Given linked list -- head = [4,5,1,9], which looks like following:
+ *`
+ *` 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
+ *`
+ *` 现有一个链表 -- head = [4,5,1,9],它可以表示为:
+ *`
+ *` Input: head = [4,5,1,9], node = 5
+ *` Output: [4,1,9]
+ *` Explanation: You are given the second node with value 5,
+ *` the linked list should become 4 -> 1 -> 9 after calling your function.
+ *`
+ *`
+ *`
+ *` 提示:你已经进入了那个节点,并不是从头开始。
+ *` 链表至少包含两个节点。
+ *` 链表中所有节点的值都是唯一的。
+ *` 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
+ *` 不要从你的函数中返回任何结果。
+ *`
+ *` 请一定要注意描述和提示!!!!
+ *`
+ *`
+ *` 解法: 直接用后面的覆盖前面的,然后将指针修改下就行
+ */
+
+public class _237_deleteNodeInLinkedList {
+
+ public static void main(String[] args) {
+
+ }
+ public static void deleteNode(ListNode node){
+ // 覆盖
+ node.val = node.next.val;
+ // 修改指针
+ node.next = node.next.next;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_581_ShortestUnsortedContinuousSubarray.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_581_ShortestUnsortedContinuousSubarray.java
new file mode 100644
index 0000000..b458aa7
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_581_ShortestUnsortedContinuousSubarray.java
@@ -0,0 +1,39 @@
+package com.leosanqing.leetcode.easy;
+
+import java.util.Arrays;
+
+/**
+ * 题目: 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
+ * 你找到的子数组应是最短的,请输出它的长度。
+ *
+ *
+ * 示例: 输入: [2, 6, 4, 8, 10, 9, 15]
+ * 输出: 5
+ * 解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
+ *
+ *
+ * 思路: 我们先将其排好序,然后用两个游标,left,right
+ * 如果出现了 数字不相等的情况,那么就说明他是我们要找的数,并且left要最小
+ * 与之相对,找到right的位置,相减+1就是我们要的长度
+ */
+class _581_ShortestUnsortedContinuousSubarray {
+ public int findUnsortedSubarray(int[] nums) {
+ int[] numsClone = nums.clone();
+ Arrays.sort(nums);
+ int left = nums.length - 1, right = 0;
+ for (int i = 0; i < nums.length; i++) {
+ if (numsClone[i] != nums[i]) {
+ left = Math.min(left, i);
+ right = Math.max(right, i);
+ }
+ }
+ return right - left > 0 ? right - left + 1 : 0;
+
+ }
+
+
+ public static void main(String[] args) {
+ Object object = new Object();
+
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_617_mergeTwoBinaryTree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_617_mergeTwoBinaryTree.java
new file mode 100644
index 0000000..4cd0e1d
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_617_mergeTwoBinaryTree.java
@@ -0,0 +1,48 @@
+package com.leosanqing.leetcode.easy;
+
+/**
+ * ` 描述: 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
+ * ` 你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,
+ * ` 否则不为 NULL 的节点将直接作为新二叉树的节点。
+ * `
+ * ` 示例: Input:
+ * ` Tree 1 Tree 2
+ * ` 1 2
+ * ` / \ / \
+ * ` 3 2 1 3
+ * ` / \ \
+ * ` 5 4 7
+ * ` Output:
+ * ` Merged tree:
+ * ` 3
+ * ` / \
+ * ` 4 5
+ * ` / \ \
+ * ` 5 4 7
+ * `
+ * `
+ * ` 思路: 使用递归遍历二叉树,然后对两者进行操作
+ */
+
+public class _617_mergeTwoBinaryTree {
+
+ static class TreeNode {
+ int val;
+ TreeNode left;
+ TreeNode right;
+ }
+
+ public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
+ if (t1 == null) {
+ return t2;
+ }
+ if (t2 == null) {
+ return t1;
+ }
+
+ t1.val += t2.val;
+ t1.left = mergeTrees(t1.left, t2.left);
+ t1.right = mergeTrees(t1.right, t2.right);
+ return t1;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_14_longestCommonPrefix.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_14_longestCommonPrefix.java
new file mode 100644
index 0000000..e639d52
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_14_longestCommonPrefix.java
@@ -0,0 +1,51 @@
+package com.leosanqing.leetcode.easy.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/3 下午5:08
+ * @Package: com.leosanqing.leetcode.easy.array
+ * @Description: Write a function to find the longest common prefix string amongst an array of strings.
+ * If there is no common prefix, return an empty string "".
+ *
+ * Example 1:
+ * Input: ["flower","flow","flight"]
+ * Output: "fl"
+ *
+ * Example 2:
+ * Input: ["dog","racecar","car"]
+ * Output: ""
+ * Explanation:
+ * There is no common prefix among the input strings.
+ * @Version: 1.0
+ */
+public class _14_longestCommonPrefix {
+ // public static void main(String[] args) {
+// BigInteger bigDecimal = BigInteger.valueOf(Math.pow(2, 478));
+// System.out.println(bigDecimal);
+// }
+
+
+ public static void main(String[] args) {
+ String[] strings = new String[]{"aa", "a"};
+
+ System.out.println(longestCommonPrefix(strings));
+ }
+
+ public static String longestCommonPrefix(String[] strs) {
+ if (strs == null || strs.length == 0) {
+ return "";
+ }
+
+ String pre = strs[0];
+ for (int i = 1; i < strs.length; i++) {
+ // 每次减去一个字符,找最长的公共前缀
+ while (strs[i].indexOf(pre) != 0) {
+ pre = pre.substring(0, pre.length() - 1);
+ }
+ }
+
+ return pre;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_1_twoSum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_1_twoSum.java
new file mode 100644
index 0000000..cac3cbe
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_1_twoSum.java
@@ -0,0 +1,36 @@
+package com.leosanqing.leetcode.easy.array;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * description:Given an array of integers, return indices of the two numbers such that they add up to a specific target.
+ * You may assume that each input would have exactly one solution, and you may not use the same element twice.
+ * 给你一个数组,返回数组两个元素相加等于目标值的元素的下标,返回其中一组解即可。同一个元素不能用两次;
+ *
+ * 如{1,2,5,6,7,2} 目标值 11
+ * 返回{2,3}
+ * solution: 利用HashMap存储元素以及下标,遍历元素,利用hash表,直接锁定另外一个符合条件的下标
+ */
+class _1_twoSum {
+ public static int[] twoSum(int[] nums, int target) {
+ Map map = new HashMap<>();
+ for (int i = 0; i < nums.length; i++) {
+ map.put(nums[i], i);
+ }
+ for (int i = 0; i < nums.length; i++) {
+ if (map.containsKey(target - nums[i])
+ && map.get(target - nums[i]) != i) {
+ return new int[]{i, map.get((target - nums[i]))};
+ }
+
+ }
+ return null;
+ }
+
+ public static void main(String[] args) {
+ int[] a = {1, 2, 5, 6};
+
+ twoSum(a, 7);
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_26_removeDuplicates.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_26_removeDuplicates.java
new file mode 100644
index 0000000..7d67561
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_26_removeDuplicates.java
@@ -0,0 +1,35 @@
+package com.leosanqing.leetcode.easy.array;
+
+/**
+ * 描述:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
+ *
+ * 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
+ *
+ * 给定 nums = [0,0,1,1,1,2,2,3,3,4],
+ *
+ * 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
+ *
+ * 你不需要考虑数组中超出新长度后面的元素。
+ *
+ *
+ * 解法:替换,
+ */
+
+
+class _26_removeDuplicates {
+ public int removeDuplicates(int[] nums) {
+ int length = 0;
+ for (int i = 0; i < nums.length; i++) {
+ if (i == 0) {
+ length++;
+ } else {
+ if (nums[i] - nums[i - 1] != 0) {
+ nums[length] = nums[i];
+ length++;
+ }
+ }
+
+ }
+ return length;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_27_removeElement.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_27_removeElement.java
new file mode 100644
index 0000000..0af7fe6
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_27_removeElement.java
@@ -0,0 +1,37 @@
+package com.leosanqing.leetcode.easy.array;
+
+/**
+ * ` description: 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
+ * ` 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
+ * ` 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
+ * `
+ * ` example: 给定 nums = [3,2,2,3], val = 3,
+ * ` 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
+ * ` 你不需要考虑数组中超出新长度后面的元素。
+ * `
+ * ` 思路: 因为他是返回数组的长度,以此来打印出所有val的数字
+ * ` 也就是说我们数组从0到那个长度之间,不会再出现val相等的数字
+ * ` 所以,我们设置一个从0开始的数字i,然后遍历数组,
+ * ` 每当遇到一个不等于 val的值,我们就用它来覆盖数组的值
+ * ` 然后i++;
+ */
+
+
+public class _27_removeElement {
+ public int removeElement(int[] nums, int val) {
+ int i = 0;
+ for (int j = 0; j < nums.length; j++) {
+ if (nums[j] != val) {
+ nums[i] = nums[j];
+ i++;
+ }
+ }
+ return i;
+ }
+
+ public static void main(String[] args) {
+ _27_removeElement a27removeElement = new _27_removeElement();
+ int[] a = {1, 2, 5, 3, 2, 1, 4, 5, 3, 5};
+ a27removeElement.removeElement(a, 2);
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_35_searchInsertPosition.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_35_searchInsertPosition.java
new file mode 100644
index 0000000..a8a9a52
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_35_searchInsertPosition.java
@@ -0,0 +1,43 @@
+package com.leosanqing.leetcode.easy.array;
+
+/**
+ * ` 题目: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
+ * ` 你可以假设数组中无重复元素。
+ * `
+ * ` 举例: 输入: [1,3,5,6], 5
+ * ` 输出: 2
+ * `
+ * ` 输入: [1,3,5,6], 2
+ * ` 输出: 1
+ * `
+ * `
+ * ` 思路: 因为题目已经给定了排好的数组,我最直接就想到用二分法
+ * ` 如果找到了就返回下标,
+ * ` 没找到就返回左边的下标,
+ * ` 如果你返回的是right,那你就会有 bug,
+ * `
+ */
+
+public class _35_searchInsertPosition {
+ public int searchInsert(int[] nums, int target) {
+ int left = 0, right = nums.length - 1, mid;
+ while (left <= right) {
+ mid = (left + right) >> 1;
+ if (nums[mid] == target)
+ return mid;
+ else if (nums[mid] > target) {
+ right = mid - 1;
+ } else {
+ left = mid + 1;
+ }
+ }
+ return left;
+ }
+
+ public static void main(String[] args) {
+ int[] a = {1, 3, 5, 7};
+ _35_searchInsertPosition a35searchInsertPosition = new _35_searchInsertPosition();
+ System.out.println(a35searchInsertPosition.searchInsert(a, 4));
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_53_maximum_subarray.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_53_maximum_subarray.java
new file mode 100644
index 0000000..46b26d0
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/array/_53_maximum_subarray.java
@@ -0,0 +1,57 @@
+package com.leosanqing.leetcode.easy.array;
+
+/**
+ * @description: 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
+ *
+ * 示例 1:
+ *
+ * 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
+ * 输出:6
+ * 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
+ * 示例 2:
+ * 输入:nums = [1]
+ * 输出:1
+ *
+ * 示例 3:
+ * 输入:nums = [0]
+ * 输出:0
+ *
+ * 示例 4:
+ * 输入:nums = [-1]
+ * 输出:-1
+ *
+ * 示例 5:
+ * 输入:nums = [-100000]
+ * 输出:-100000
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/maximum-subarray
+ * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ * @author: rtliu
+ * @date: 2021/4/9 10:09 上午
+ */
+public class _53_maximum_subarray {
+
+ public static void main(String[] args) {
+ System.out.println(maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}));
+ System.out.println(maxSubArray(new int[]{2}));
+ System.out.println(maxSubArray(new int[]{-1, 2, -1}));
+ System.out.println(maxSubArray(new int[]{-1, -1, -2, -2}));
+ }
+
+ /**
+ * 这个题思路很简单,从左到右遍历,如果前面的和小于当前数,则舍弃之前的数组,从当前位置重新开始找
+ *
+ * @param nums
+ * @return
+ */
+ public static int maxSubArray(int[] nums) {
+ int max = nums[0];
+ int sum = 0;
+ for (int num : nums) {
+ sum = Math.max(sum + num,num);
+ max = Math.max(sum, max);
+ }
+ return max;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_118_pascals_triangle.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_118_pascals_triangle.java
new file mode 100644
index 0000000..4bd382e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_118_pascals_triangle.java
@@ -0,0 +1,41 @@
+package com.leosanqing.leetcode.easy.list;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 下午4:05
+ * @Package: com.leosanqing.leetcode.easy.list
+ * @Description: 1
+ * ` Given a non-negative integer numRows, generate the first numRows of Pascal's triangle.
+ * ` In Pascal's triangle, each number is the sum of the two numbers directly above it.
+ * ` Example:
+ * ` Input: 5
+ * ` Output: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
+ * @Version: 1.0
+ */
+public class _118_pascals_triangle {
+ public static void main(String[] args) {
+ System.out.println(JSON.toJSONString(generate(5)));
+ }
+ public static List> generate(int numRows) {
+ List> answer = new ArrayList<>();
+
+ for (int i = 1; i <= numRows; i++) {
+ List list = new ArrayList<>(i);
+ for (int j = 0; j < i; j++) {
+ if (j == 0 || j == i - 1) {
+ list.add(1);
+ continue;
+ }
+ list.add(answer.get(i - 2).get(j - 1) + answer.get(i - 2).get(j));
+ }
+ answer.add(list);
+ }
+
+ return answer;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_119_pascals_triangleII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_119_pascals_triangleII.java
new file mode 100644
index 0000000..ec94e2b
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_119_pascals_triangleII.java
@@ -0,0 +1,40 @@
+package com.leosanqing.leetcode.easy.list;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 下午4:45
+ * @Package: com.leosanqing.leetcode.easy.list
+ * @Description: 1
+ * ` Given a non-negative index k where k ≤ 33, return the kth index row of the Pascal's triangle.
+ * ` Note that the row index starts from 0.
+ * ` In Pascal's triangle, each number is the sum of the two numbers directly above it.
+ * ` Example:
+ * ` Input: 3
+ * ` Output: [1,3,3,1]
+ * @Version: 1.0
+ */
+public class _119_pascals_triangleII {
+ public static void main(String[] args) {
+ generate(3);
+ }
+
+ public static List generate(int numRows) {
+ List answer = new ArrayList<>(numRows + 1);
+
+ answer.add(0, 1);
+
+ for (int i = 1; i <= numRows; i++) {
+ Integer integer = 1;
+ answer.add(i, 1);
+ for (int j = 1; j < i; j++) {
+ Integer integer1 = answer.get(j);
+ answer.set(j, integer + integer1);
+ integer = integer1;
+ }
+ }
+ return answer;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_141_linked_list_cycle.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_141_linked_list_cycle.java
new file mode 100644
index 0000000..bec4f98
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_141_linked_list_cycle.java
@@ -0,0 +1,46 @@
+package com.leosanqing.leetcode.easy.list;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 下午4:15
+ * @Package: com.leosanqing.leetcode.easy.list
+ * @Description: 1
+ * ` Given a linked list, determine if it has a cycle in it.
+ * ` To represent a cycle in the given linked list,
+ * ` we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to.
+ * ` If pos is -1, then there is no cycle in the linked list.
+ * ` Example 1:
+ * ` Input: head = [3,2,0,-4], pos = 1
+ * ` Output: true
+ * ` Explanation: There is a cycle in the linked list, where tail connects to the second node.
+ * ` Example 2:
+ * ` Input: head = [1,2], pos = 0
+ * ` Output: true
+ * ` Explanation: There is a cycle in the linked list, where tail connects to the first node.
+ * @Version: 1.0
+ */
+public class _141_linked_list_cycle {
+ /**
+ * 设置两个指针 一个快指针 一个慢指针 ,只要出现两个指针指向的一样,那就说明有环
+ *
+ * @param head
+ * @return
+ */
+ public boolean hasCycle(ListNode head) {
+ ListNode fast = head;
+ ListNode slow = head;
+ while (fast != null && fast.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+ if (fast == slow) {
+ return true;
+ }
+ }
+
+ return false;
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_21_merge_two_sorted_lists.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_21_merge_two_sorted_lists.java
new file mode 100644
index 0000000..5f62dc4
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_21_merge_two_sorted_lists.java
@@ -0,0 +1,99 @@
+package com.leosanqing.leetcode.easy.list;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/7 下午4:46
+ * @Package: com.leosanqing.leetcode.easy.list
+ * @Description: Merge two sorted linked lists and return it as a new sorted list.
+ * The new list should be made by splicing together the nodes of the first two lists.
+ * Example:
+ * Input: 1->2->4, 1->3->4
+ * Output: 1->1->2->3->4->4
+ * @Version: 1.0
+ */
+public class _21_merge_two_sorted_lists {
+
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(4);
+ ListNode node2 = new ListNode(2, node1);
+ ListNode node3 = new ListNode(1, node2);
+ ListNode node4 = new ListNode(4);
+ ListNode node5 = new ListNode(3, node4);
+ ListNode node6 = new ListNode(1, node5);
+
+ System.out.println(mergeTwoLists(node3, node6));
+ }
+
+ public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
+
+ // 先处理极限情况
+ if (l1 == null && l2 == null) {
+ return new ListNode();
+ }
+ if (l1 == null) {
+ return l2;
+ }
+ if (l2 == null) {
+ return l1;
+ }
+
+ // 放一个虚拟的头,用来预防各种极限值,很多解法都会使用这种方式
+ ListNode newList = new ListNode();
+ ListNode fakeHead = newList;
+ ListNode p1 = l1;
+ ListNode p2 = l2;
+
+ while (p1 != null && p2 != null) {
+ if (p1.val <= p2.val) {
+ newList.next = p1;
+ p1 = p1.next;
+ } else {
+ newList.next = p2;
+ p2 = p2.next;
+ }
+ newList = newList.next;
+ }
+
+ // 如果还有剩的
+ if (p1 != null) {
+ newList.next = p1;
+ }
+
+ if (p2 != null) {
+ newList.next = p2;
+ }
+
+ return fakeHead.next;
+ }
+
+ public ListNode mergeTwoLists1(ListNode l1, ListNode l2) {
+
+ ListNode cur = new ListNode();
+ ListNode fakeHead = cur;
+ ListNode n1 = l1;
+ ListNode n2 = l2;
+
+ while (n1 != null && n2 != null) {
+ if (n1.val < n2.val) {
+ cur.next = n1;
+ n1 = n1.next;
+ } else {
+ cur.next = n2;
+ n2 = n2.next;
+ }
+ cur = cur.next;
+ }
+ // 如果还有剩的
+ if (n1 != null) {
+ cur.next = n1;
+ }
+
+ if (n2 != null) {
+ cur.next = n2;
+ }
+
+ return fakeHead.next;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_876_middle_of_the_linked_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_876_middle_of_the_linked_list.java
new file mode 100644
index 0000000..d8b0463
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/list/_876_middle_of_the_linked_list.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.easy.list;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/22 上午9:28
+ * @Package: com.leosanqing.leetcode.easy.list
+ * @Description: 1
+ * Given a non-empty, singly linked list with head node head, return a middle node of linked list.
+ * If there are two middle nodes, return the second middle node.
+ * Example 1:
+ * Input: [1,2,3,4,5]
+ * Output: Node 3 from this list (Serialization: [3,4,5]) The returned node has value 3.
+ * (The judge's serialization of this node is [3,4,5]).
+ * Note that we returned a ListNode object ans, such that: ans.val = 3,
+ * ans.next.val = 4, ans.next.next.val = 5, and ans.next.next.next = NULL.
+ * Example 2:
+ * Input: [1,2,3,4,5,6]
+ * Output: Node 4 from this list (Serialization: [4,5,6])
+ * Since the list has two middle nodes with values 3 and 4, we return the second one.
+ * @Version: 1.0
+ */
+public class _876_middle_of_the_linked_list {
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(6);
+ ListNode node2 = new ListNode(5, node1);
+ ListNode node3 = new ListNode(4, node2);
+ ListNode node4 = new ListNode(3,node3);
+ ListNode node5 = new ListNode(2, node4);
+
+ middleNode(node5);
+ }
+
+ public static ListNode middleNode(ListNode head) {
+
+ ListNode fakeHead = new ListNode();
+ fakeHead.next = head;
+
+ ListNode fastNode = fakeHead;
+ ListNode slowNode = fastNode;
+ while (fastNode != null ) {
+ slowNode =slowNode.next;
+ fastNode = fastNode.next;
+ if(fastNode == null){
+ return slowNode;
+ }
+ fastNode = fastNode.next;
+ }
+
+ return slowNode;
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_263_uglyNumber.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_263_uglyNumber.java
new file mode 100644
index 0000000..61c8b6d
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_263_uglyNumber.java
@@ -0,0 +1,35 @@
+package com.leosanqing.leetcode.easy.num;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/23 下午3:34
+ * @Package: com.leosanqing.leetcode.easy.num
+ * @Description: Write a program to check whether a given number is an ugly number.
+ * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5.
+ * @Version: 1.0
+ */
+public class _263_uglyNumber {
+ public static void main(String[] args) {
+ System.out.println(isUgly(15));
+ }
+
+ public static boolean isUgly(int num) {
+
+ if (num == 0) {
+ return false;
+ }
+
+ while (num != 1) {
+ if (num % 5 == 0) {
+ num /= 5;
+ } else if (num % 3 == 0) {
+ num /= 3;
+ } else if (num % 2 == 0) {
+ num /= 2;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_70_climbing_stairs.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_70_climbing_stairs.java
new file mode 100644
index 0000000..1e4bb7b
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_70_climbing_stairs.java
@@ -0,0 +1,56 @@
+package com.leosanqing.leetcode.easy.num;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午2:26
+ * @Package: com.leosanqing.leetcode.easy.num
+ * @Description: 1
+ * ` You are climbing a stair case.
+ * ` It takes n steps to reach to the top.
+ * ` Each time you can either climb 1 or 2 steps.
+ * ` In how many distinct ways can you climb to the top?
+ * ` Example 1:
+ * ` Input: 2
+ * ` Output: 2
+ * ` Explanation:
+ * ` There are two ways to climb to the top.
+ * ` 1. 1 step + 1 step 2. 2 steps
+ * ` Example 2:
+ * ` Input: 3
+ * ` Output: 3
+ * ` Explanation:
+ * ` There are three ways to climb to the top.
+ * ` 1. 1 step + 1 step + 1 step
+ * ` 2. 1 step + 2 steps
+ * ` 3. 2 steps + 1 step
+ * @Version: 1.0
+ */
+public class _70_climbing_stairs {
+ public static void main(String[] args) {
+ System.out.println(climbStairs(7));
+ }
+
+ /**
+ * 仔细看这个题 其实是斐波那契数列的变种,解题方法一致
+ *
+ * 我们可以使用栈,也可以使用 DP,但是 DP明显优于栈
+ *
+ * @param n
+ * @return
+ */
+ public static int climbStairs(int n) {
+ if (n <= 3) {
+ return n;
+ }
+ int pre = 3;
+ int prePre = 2;
+ int cur = 0;
+ for (int i = 4; i <= n; i++) {
+ cur = pre + prePre;
+ prePre = pre;
+ pre = cur;
+ }
+
+ return cur;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_7_reverseInteger.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_7_reverseInteger.java
new file mode 100644
index 0000000..5d63324
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_7_reverseInteger.java
@@ -0,0 +1,38 @@
+package com.leosanqing.leetcode.easy.num;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/3 下午3:19
+ * @Package: com.leosanqing.leetcode.easy.num
+ * @Description: ` Given a 32-bit signed integer, reverse digits of an integer.
+ * ` Example 1:
+ * ` Input: 123
+ * ` Output: 321
+ * ` Example 2:
+ * ` Input: -123
+ * ` Output: -321
+ * ` Example 3:
+ * ` Input: 120
+ * ` Output: 21
+ * ` Note:
+ * ` Assume we are dealing with an environment which could only store integers
+ * ` within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem,
+ * ` assume that your function returns 0 when the reversed integer overflows.
+ * @Version: 1.0
+ */
+public class _7_reverseInteger {
+ public static void main(String[] args) {
+ _7_reverseInteger reverseInteger = new _7_reverseInteger();
+ System.out.println(reverseInteger.reverse(-1200));
+ }
+
+ public int reverse(int x) {
+ long res = 0;
+ while (x != 0) {
+ res *= 10;
+ res += x % 10;
+ x /= 10;
+ }
+ return (int) res == res ? (int) res : 0;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_9_palindrome_number.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_9_palindrome_number.java
new file mode 100644
index 0000000..f1ec6c3
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/num/_9_palindrome_number.java
@@ -0,0 +1,70 @@
+package com.leosanqing.leetcode.easy.num;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/3 下午3:24
+ * @Package: com.leosanqing.leetcode.easy.num
+ * @Description: `
+ * ` Determine whether an integer is a palindrome.
+ * ` An integer is a palindrome when it reads the same backward as forward.
+ * `
+ * ` Example 1:
+ * ` Input: 121
+ * ` Output: true
+ * ` Example 2:
+ * ` Input: -121
+ * ` Output: false
+ * ` Explanation:
+ * ` From left to right, it reads -121.
+ * ` From right to left, it becomes 121-.
+ * ` Therefore it is not a palindrome.
+ * ` Example 3:
+ * ` Input: 10
+ * ` Output: false
+ * ` Explanation:
+ * ` Reads 01 from right to left. Therefore it is not a palindrome.
+ * @Version: 1.0
+ */
+public class _9_palindrome_number {
+
+ public static void main(String[] args) {
+ System.out.println(isPalindrome(12121));
+ }
+
+ public static boolean isPalindrome(int x) {
+ // 如果小于0 或者大于零 但是以0结尾的都不是
+ if (x < 0 || (x != 0 && x % 10 == 0)) {
+ return false;
+ }
+
+ int rev = 0;
+ // 只需要一半,就可以进行匹配
+ while (x > rev) {
+ rev = rev * 10 + x % 10;
+ x /= 10;
+ }
+ return rev == x || x == rev / 10;
+ }
+
+ /**
+ * 使用字符串
+ *
+ * @param x
+ * @return
+ */
+ public static boolean isPalindrome2(int x) {
+ // 如果小于0 或者大于零 但是以0结尾的都不是
+ if (x < 0 || (x != 0 && x % 10 == 0)) {
+ return false;
+ }
+
+ String s = String.valueOf(x);
+
+ for (int i = 0; i < s.length() / 2; i++) {
+ if (s.charAt(i) != s.charAt(s.length() - i - 1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_20_valid_parentheses.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_20_valid_parentheses.java
new file mode 100644
index 0000000..1ce4f5f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_20_valid_parentheses.java
@@ -0,0 +1,64 @@
+package com.leosanqing.leetcode.easy.string;
+
+import java.util.Stack;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/7 下午4:20
+ * @Package: com.leosanqing.leetcode.easy.string
+ * @Description: ` Given a string containing just the characters '(', ')', '{', '}', '[' and ']',
+ * ` determine if the input string is valid.
+ * ` An input string is valid if:
+ * ` Open brackets must be closed by the same type of brackets.
+ * ` Open brackets must be closed in the correct order.
+ * ` Note that an empty string is also considered valid.
+ * ` Example 1:
+ * ` Input: "()"
+ * ` Output: true
+ * ` Example 2:
+ * ` Input: "()[]{}"
+ * ` Output: true
+ * ` Example 3:
+ * ` Input: "(]"
+ * ` Output: false
+ * ` Example 4:
+ * ` Input: "([)]"
+ * ` Output: false
+ * ` Example 5:
+ * ` Input: "{[]}"
+ * ` Output: true
+ * @Version: 1.0
+ */
+public class _20_valid_parentheses {
+ public static void main(String[] args) {
+
+ }
+
+ public boolean isValid(String s) {
+
+ if (s == null || "".equals(s)) {
+ return true;
+ }
+
+ char[] charArray = s.toCharArray();
+ if (charArray.length % 2 != 0) {
+ return false;
+ }
+
+ Stack stack = new Stack<>();
+ for (char c : charArray) {
+ if (c == '[') {
+ stack.push(']');
+ } else if (c == '(') {
+ stack.push(')');
+ } else if (c == '{') {
+ stack.push('}');
+ } else if (stack.isEmpty() || stack.pop() != c) {
+ return false;
+ }
+
+ }
+
+ return stack.isEmpty();
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_242_validAnagram.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_242_validAnagram.java
new file mode 100644
index 0000000..718cfdf
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_242_validAnagram.java
@@ -0,0 +1,52 @@
+package com.leosanqing.leetcode.easy.string;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/22 下午4:48
+ * @Package: com.leosanqing.leetcode.easy.string
+ * @Description: Given two strings s and t , write a function to determine if t is an anagram of s.
+ * @Version: 1.0
+ *
+ *
+ * Example 1:
+ *
+ * Input: s = "anagram", t = "nagaram"
+ * Output: true
+ *
+ * Example 2:
+ *
+ * Input: s = "rat", t = "car"
+ * Output: false
+ * Note:
+ * You may assume the string contains only lowercase alphabets.
+ *
+ * Follow up:
+ * What if the inputs contain unicode characters? How would you adapt your solution to such case?
+ */
+public class _242_validAnagram {
+
+ public static void main(String[] args) {
+
+ }
+
+ public static boolean isAnagram(String s, String t) {
+ int[] alphabet = new int[26];
+ if (s.length() != t.length()) {
+ return false;
+ }
+ for (int i = 0; i < s.length(); i++) {
+ alphabet[s.charAt(i) - 'a']++;
+ }
+ for (int i = 0; i < t.length(); i++) {
+ alphabet[t.charAt(i) - 'a']--;
+ }
+
+ for (int i : alphabet) {
+ if (i != 0) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_60_permutation_sequence.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_60_permutation_sequence.java
new file mode 100644
index 0000000..e405bef
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/string/_60_permutation_sequence.java
@@ -0,0 +1,65 @@
+package com.leosanqing.leetcode.easy.string;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/15 下午5:39
+ * @Package: com.leosanqing.leetcode.easy.string
+ * @Description: 1
+ * ` The set [1,2,3,...,n] contains a total of n! unique permutations.
+ * ` By listing and labeling all of the permutations in order,
+ * ` we get the following sequence for n = 3:
+ * ` "123" "132" "213" "231" "312" "321" Given n and k,
+ * ` return the kth permutation sequence.
+ * ` 集[1,2,3,...,n]总共包含n!独特的排列。
+ * ` 通过按顺序列出和标记所有排列,
+ * ` 我们得到n = 3的以下序列:
+ * ` “ 123”“ 132”“ 213”“ 231”“ 312”“ 321”给定n和k,
+ * ` 返回第k个排列序列。
+ * ` Note:
+ * ` Given n will be between 1 and 9 inclusive.
+ * ` Given k will be between 1 and n! inclusive.
+ * ` Example 1:
+ * ` Input: n = 3, k = 3
+ * ` Output: "213"
+ * ` Example 2:
+ * ` Input: n = 4, k = 9
+ * ` Output: "2314"
+ * @Version: 1.0
+ */
+public class _60_permutation_sequence {
+
+ public static void main(String[] args) {
+ System.out.println(getPermutation(8,30654));
+ }
+ public static String getPermutation(int n, int k) {
+
+ LinkedList notUsed = new LinkedList<>();
+
+ int sum = 1;
+ for (int i = 1; i <= n; i++) {
+ notUsed.add(i);
+ if(i == n){
+ break;
+ }
+ sum *= i;
+ }
+
+ StringBuilder result = new StringBuilder();
+ k--;
+
+ while (true) {
+ result.append(notUsed.remove(k / sum));
+ k = k % sum;
+ if(notUsed.isEmpty()){
+ break;
+ }
+ sum /= notUsed.size();
+ }
+ return result.toString();
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_100_same_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_100_same_tree.java
new file mode 100644
index 0000000..df2ae29
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_100_same_tree.java
@@ -0,0 +1,59 @@
+package com.leosanqing.leetcode.easy.tree;
+
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/27 上午11:41
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given two binary trees, write a function to check if they are the same or not.
+ * ` Two binary trees are considered the same if they are structurally identical and the nodes have the same
+ * value.
+ * ` Example 1:
+ * ` Input: 1 1
+ * ` / \ / \
+ * ` 2 3 2 3
+ * ` [1,2,3], [1,2,3]
+ * ` Output: true
+ * ` Example 2:
+ * ` Input:
+ * ` 1 1
+ * ` / \
+ * ` 2 2
+ * ` [1,2], [1,null,2]
+ * ` Output: false
+ * ` Example 3:
+ * ` Input:
+ * ` 1 1
+ * ` / \ / \
+ * ` 2 1 1 2
+ * ` [1,2,1], [1,1,2]
+ * ` Output: false
+ * @Version: 1.0
+ */
+public class _100_same_tree {
+ public boolean isSameTree(TreeNode p, TreeNode q) {
+
+ return backTrace(p,q);
+ }
+
+ private static boolean backTrace(TreeNode p, TreeNode q) {
+ if (p == null && q == null) {
+ return true;
+ }
+
+ if (p == null || q == null) {
+ return false;
+ }
+
+ if (p.val != q.val) {
+ return false;
+ }
+ return backTrace(p.left, q.left) && backTrace(p.right, q.right);
+
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_101_symmetric_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_101_symmetric_tree.java
new file mode 100644
index 0000000..5c9c2cd
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_101_symmetric_tree.java
@@ -0,0 +1,50 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/27 下午3:46
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
+ * ` For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
+ * ` 1
+ * ` / \
+ * ` 2 2
+ * ` / \ / \
+ * ` 3 4 4 3
+ * ` But the following [1,2,2,null,3,null,3] is not:
+ * ` 1
+ * ` / \
+ * ` 2 2
+ * ` \ \
+ * ` 3 3
+ * @Version: 1.0
+ */
+public class _101_symmetric_tree {
+
+ public static boolean isSymmetric(TreeNode root) {
+ if (root == null) {
+ return true;
+ }
+ return backtrace(root.left, root.right);
+ }
+
+ private static boolean backtrace(TreeNode left, TreeNode right) {
+ if (left == null && right == null) {
+ return true;
+ }
+ if (left == null || right == null) {
+ return false;
+ }
+
+ if (left.val != right.val) {
+ return false;
+ }
+
+ return backtrace(left.left, right.right)
+ && backtrace(left.right, right.left);
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_104_maximum_depth_of_binary_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_104_maximum_depth_of_binary_tree.java
new file mode 100644
index 0000000..1dffe71
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_104_maximum_depth_of_binary_tree.java
@@ -0,0 +1,59 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/28 下午4:31
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given a binary tree, find its maximum depth.
+ * ` The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
+ * ` Note: A leaf is a node with no children.
+ * ` Example: Given binary tree [3,9,20,null,null,15,7],
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` return its depth = 3.
+ * @Version: 1.0
+ */
+public class _104_maximum_depth_of_binary_tree {
+
+
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(3);
+ treeNode.left = new TreeNode(9);
+ treeNode.right = new TreeNode(20);
+ treeNode.right.left = new TreeNode(1);
+ treeNode.right.right = new TreeNode(7);
+ System.out.println(maxDepth(treeNode));
+ }
+
+ static class Num{
+ int max;
+ }
+
+ public static int maxDepth(TreeNode root) {
+ Num num = new Num();
+ num.max = 0;
+ if (root == null) {
+ return 0;
+ }
+ backtrace(root, 0, num);
+ return num.max;
+ }
+
+ private static void backtrace(TreeNode root, int curInt, Num max) {
+ if (root == null) {
+ return;
+ }
+
+ max.max = Math.max(++curInt, max.max);
+
+ backtrace(root.left, curInt, max);
+ backtrace(root.right, curInt, max);
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_107_binary_tree_level_order_traversalII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_107_binary_tree_level_order_traversalII.java
new file mode 100644
index 0000000..13e1420
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_107_binary_tree_level_order_traversalII.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/29 下午4:15
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given a binary tree, return the bottom-up level order traversal of its nodes' values.
+ * ` (ie, from left to right, level by level from leaf to root).
+ * ` For example: Given binary tree [3,9,20,null,null,15,7],
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` return its bottom-up level order traversal as:
+ * ` [
+ * ` [15,7],
+ * ` [9,20],
+ * ` [3]
+ * ` ]
+ * @Version: 1.0
+ */
+public class _107_binary_tree_level_order_traversalII {
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(3);
+ treeNode.left = new TreeNode(9);
+ treeNode.right = new TreeNode(20);
+ treeNode.right.left = new TreeNode(15);
+ treeNode.right.right = new TreeNode(7);
+ levelOrderBottom(treeNode);
+ }
+
+ public static List> levelOrderBottom(TreeNode root) {
+
+ List> answer = new ArrayList<>();
+
+ backTrace(answer, 0, root);
+ Collections.reverse(answer);
+ return answer;
+ }
+
+
+ private static void backTrace(List> answer, int depth, TreeNode root) {
+ if (root == null) {
+ return;
+ }
+
+ if (answer.size() > depth) {
+ answer.get(depth).add(root.val);
+ } else {
+ List list = new ArrayList<>();
+ list.add(root.val);
+ answer.add(new ArrayList<>(list));
+ }
+
+ backTrace(answer, depth + 1, root.left);
+ backTrace(answer, depth + 1, root.right);
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_108_convert_sorted_array_to_binary_search_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_108_convert_sorted_array_to_binary_search_tree.java
new file mode 100644
index 0000000..1d8ce25
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_108_convert_sorted_array_to_binary_search_tree.java
@@ -0,0 +1,58 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/30 上午9:26
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
+ * ` For this problem,
+ * ` a height-balanced binary tree is defined as a binary tree in
+ * ` which the depth of the two subtrees of every node never differ by more than 1.
+ * `
+ * `
+ * ` 给定一个数组,其中元素按升序排序,请将其转换为高度平衡的BST。
+ * ` 比如这个问题,
+ * ` 高度平衡的二叉树被定义为
+ * ` 每个节点的两个子树的深度相差不超过1。
+ * ` Example:
+ * ` Given the sorted array: [-10,-3,0,5,9],
+ * ` One possible answer is: [0,-3,9,-10,null,5],
+ * ` which represents the following height balanced BST:
+ * ` 0
+ * ` / \
+ * ` -3 9
+ * ` / /
+ * ` -10 5
+ * @Version: 1.0
+ */
+public class _108_convert_sorted_array_to_binary_search_tree {
+
+ public static void main(String[] args) {
+ TreeNode treeNode = sortedArrayToBST(new int[]{-10, -3, 0, 5, 9});
+ System.out.println(111);
+ }
+
+ public static TreeNode sortedArrayToBST(int[] nums) {
+ return backTrace(nums, 0, nums.length - 1);
+
+ }
+
+ private static TreeNode backTrace(int[] nums, int left, int right) {
+ if (left > right) {
+ return null;
+ }
+
+ int mid = (right - left) / 2 + left;
+
+ TreeNode root = new TreeNode(nums[mid]);
+
+ root.left = backTrace(nums, left, mid - 1);
+ root.right = backTrace(nums, mid + 1, right);
+ return root;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_110_balanced_binary_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_110_balanced_binary_tree.java
new file mode 100644
index 0000000..599ffaa
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_110_balanced_binary_tree.java
@@ -0,0 +1,74 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/30 下午3:06
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given a binary tree, determine if it is height-balanced.
+ * ` For this problem, a height-balanced binary tree is defined as:
+ * ` a binary tree in which the left and right subtrees of every node differ in height by no more than 1.
+ * ` Example 1:
+ * ` Given the following tree [3,9,20,null,null,15,7]:
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` Return true.
+ * ` Example 2:
+ * ` Given the following tree [1,2,2,3,3,null,null,4,4]:
+ * ` 1
+ * ` / \
+ * ` 2 2
+ * ` / \
+ * ` 3 3
+ * ` / \
+ * ` 4 4
+ * @Version: 1.0
+ */
+public class _110_balanced_binary_tree {
+
+ private static boolean result = true;
+
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(1);
+ treeNode.left = new TreeNode(2);
+ treeNode.right = new TreeNode(2);
+ treeNode.left.left = new TreeNode(3);
+ treeNode.left.right = new TreeNode(3);
+ treeNode.right.left = new TreeNode(3);
+ treeNode.right.right = new TreeNode(3);
+ treeNode.left.left.left = new TreeNode(4);
+ treeNode.left.left.right = new TreeNode(4);
+ treeNode.left.right.left = new TreeNode(4);
+ treeNode.left.right.right = new TreeNode(4);
+ treeNode.right.left.left = new TreeNode(4);
+ treeNode.right.left.right = new TreeNode(4);
+ treeNode.left.left.left.left = new TreeNode(4);
+ treeNode.left.left.left.right = new TreeNode(4);
+ System.out.println(isBalanced(treeNode));
+ }
+
+ public static boolean isBalanced(TreeNode root) {
+ result = true;
+ backTrace(root);
+ return result;
+ }
+
+ private static int backTrace(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ int left = backTrace(root.left);
+ int right = backTrace(root.right);
+
+ if (Math.abs(left - right) > 1) {
+ result = false;
+ }
+
+ return 1 + Math.max(left, right);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_111_minimum_depth_of_binary_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_111_minimum_depth_of_binary_tree.java
new file mode 100644
index 0000000..93c519f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/tree/_111_minimum_depth_of_binary_tree.java
@@ -0,0 +1,35 @@
+package com.leosanqing.leetcode.easy.tree;
+
+import com.leosanqing.leetcode.medium.tree.TreeNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/30 下午3:53
+ * @Package: com.leosanqing.leetcode.easy.tree
+ * @Description: 1
+ * ` Given a binary tree, find its minimum depth.
+ * ` The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
+ * ` Note: A leaf is a node with no children.
+ * ` Example:
+ * ` Given binary tree [3,9,20,null,null,15,7],
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` return its minimum depth = 2.
+ * @Version: 1.0
+ */
+public class _111_minimum_depth_of_binary_tree {
+
+
+ public int minDepth(TreeNode root) {
+ if(root == null) {
+ return 0;
+ }
+ if(root.left == null || root.right == null) {
+ return 1 + Math.max(minDepth(root.left), minDepth(root.right));
+ }
+ return 1 + Math.min(minDepth(root.left), minDepth(root.right));
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/hard/list/_123_best_time_to_buy_and_sell_stockIII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/hard/list/_123_best_time_to_buy_and_sell_stockIII.java
new file mode 100644
index 0000000..7c15335
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/hard/list/_123_best_time_to_buy_and_sell_stockIII.java
@@ -0,0 +1,61 @@
+package com.leosanqing.leetcode.hard.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 上午10:57
+ * @Package: com.leosanqing.leetcode.hard.list
+ * @Description: 1
+ * ` Say you have an array for which the ith element is the price of a given stock on day i.
+ * ` Design an algorithm to find the maximum profit.
+ * ` You may complete at most two transactions.
+ * ` Note: You may not engage in multiple transactions at the same time
+ * ` (i.e., you must sell the stock before you buy again).
+ * ` Example 1:
+ * ` Input: [3,3,5,0,0,3,1,4]
+ * ` Output: 6
+ * ` Explanation:
+ * ` Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
+ * ` Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
+ * ` Example 2:
+ * ` Input: [1,2,3,4,5]
+ * ` Output: 4
+ * ` Explanation:
+ * ` Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
+ * ` Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
+ * ` engaging multiple transactions at the same time. You must sell before buying again.
+ * ` Example 3:
+ * ` Input: [7,6,4,3,1]
+ * ` Output: 0
+ * ` Explanation:
+ * ` In this case, no transaction is done, i.e. max profit = 0.
+ * @Version: 1.0
+ */
+public class _123_best_time_to_buy_and_sell_stockIII {
+ public static void main(String[] args) {
+
+ maxProfit(new int[]{1, 2, 3, 4, 5});
+ }
+
+ public static int maxProfit(int[] prices) {
+ if (prices == null || prices.length < 2) {
+ return 0;
+ }
+ int totalK = 2;
+ int[][] dp = new int[totalK + 1][prices.length];
+ for (int k = 1; k <= totalK; k++) {
+ //profit = 0 when k = 0
+ for (int i = 1; i < prices.length; i++) {
+ //buy on day 0, sell on day i
+ int maxProfitSellOnDayI = Math.max(0, prices[i] - prices[0]);
+ //buy on day j, sell on day i
+ for (int j = 1; j < i; j++) {
+ maxProfitSellOnDayI = Math.max(maxProfitSellOnDayI, dp[k - 1][j - 1] + prices[i] - prices[j]);
+ }
+ //sell on day i OR not
+ dp[k][i] = Math.max(dp[k][i - 1], maxProfitSellOnDayI);
+ }
+ }
+ return dp[totalK][prices.length - 1];
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_201_bitwiseANDOfNumbersRange.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_201_bitwiseANDOfNumbersRange.java
new file mode 100644
index 0000000..864f81a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_201_bitwiseANDOfNumbersRange.java
@@ -0,0 +1,63 @@
+package com.leosanqing.leetcode.medium;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/1 上午10:45
+ * @Package: medium
+ * @Description: `
+ * ` Given a range [m, n] where 0 <= m <= n <= 2147483647,
+ * ` return the bitwise AND of all numbers in this range, inclusive.
+ * `
+ * ` 给定一个范围
+ * ` 返回这个范围内的所有数字的 按位与 的 和
+ * `
+ * ` Example 1:
+ * `
+ * ` Input: [5,7]
+ * ` Output: 4
+ * ` Example 2:
+ * `
+ * ` Input: [0,1]
+ * ` Output: 0
+ * `
+ * `
+ * @Version: 1.0
+ */
+public class _201_bitwiseANDOfNumbersRange {
+
+ public static void main(String[] args) {
+
+ System.out.println(solution(5, 12));
+
+ System.out.println(solution(5, 12));
+ }
+
+
+ /**
+ * 思路很简单,只要从 m 到 n 的任意一个数字中的一位是0, 那么那一位 不管怎么 & 都是0
+ * 比如 [5-12]
+ * 5 101
+ * 6 110
+ * 7 111
+ * 8 1000
+ * 9 1001
+ * 10 1010
+ * 11 1011
+ * 12 1010
+ *
+ * 我们看 只要我们找到他的最前面几位是一样的时候,再给他补完后面的位数,就找到了
+ *
+ * @param m
+ * @param n
+ * @return
+ */
+ private static int solution(int m, int n) {
+ int step = 0;
+ while (m != n) {
+ m >>= 1;
+ n >>= 1;
+ step++;
+ }
+ return m << step;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_73_setMatrixZeroes.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_73_setMatrixZeroes.java
new file mode 100644
index 0000000..0d9be9e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/_73_setMatrixZeroes.java
@@ -0,0 +1,59 @@
+package com.leosanqing.leetcode.medium;
+
+/**
+ * 题目: 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
+ *
+ * 示例:输入:
+ * [
+ * [1,1,1],
+ * [1,0,1],
+ * [1,1,1]
+ * ]
+ * 输出:
+ * [
+ * [1,0,1],
+ * [0,0,0],
+ * [1,0,1]
+ * ]
+ *
+ * 思路: 把矩阵的第一行和第一列作为标志位,如果该行或者该列有0,那么他就置为0
+ * 然后再遍历,替换
+ */
+class _73_setMatrixZeroes {
+ public void setZeroes(int[][] matrix) {
+ if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
+ return;
+ }
+
+ int col0 = 1, rows = matrix.length, cols = matrix[0].length;
+
+
+ for (int i = 0; i < rows; i++) {
+ if (matrix[i][0] == 0) {
+ col0 = 0;
+ }
+ for (int j = 0; j < cols; j++) {
+ if (matrix[i][j] == 0) {
+ matrix[i][0] = 0;
+ matrix[0][j] = 0;
+ }
+
+ }
+ }
+
+ // 遍历集合,把他们变成0
+ for (int i = rows - 1; i >= 0; i--) {
+ for (int j = cols - 1; j >= 1; j--) {
+ if (matrix[0][j] == 0 || matrix[i][0] == 0) {
+ matrix[i][j] = 0;
+ }
+ }
+
+ if (col0 == 0) {
+ matrix[i][0] = 0;
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/TaskEvData.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/TaskEvData.java
new file mode 100644
index 0000000..f0eee3f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/TaskEvData.java
@@ -0,0 +1,31 @@
+package com.leosanqing.leetcode.medium.array;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * 任务实体
+ * @author zdsys-008
+ */
+@Getter
+@Setter
+public class TaskEvData implements Serializable {
+ /**
+ * 任务状态码:0[过程中]>>1[成功]>>2[失败]
+ */
+ private int status;
+ /**
+ * 任务状态解读:[运行中]>>[运行成功]>>[运行失败]
+ */
+ private String statusMsg;
+ /**
+ * 状态成功时,对应的cosurl
+ */
+ private String url;
+ /**
+ * 截图成功时,对应的存证hash
+ */
+ private String hash;
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/Test.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/Test.java
new file mode 100644
index 0000000..3c42628
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/Test.java
@@ -0,0 +1,56 @@
+package com.leosanqing.leetcode.medium.array;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.lang.reflect.Field;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 下午4:15
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description:
+ * @Version:
+ */
+public class Test {
+
+ /**
+ * 数据处理 >> 暂目前只支持int + String两种类型
+ * @param jsonObject
+ * @param clazz
+ * @param
+ * @return
+ */
+ private static T dataHandle(JSONObject jsonObject, Class clazz, String data) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ if (jsonObject != null && jsonObject.containsKey("retCode") && 0 == jsonObject.getInteger("retCode")) {
+ JSONObject dataJson = jsonObject.getJSONObject(data);
+ Field[] fields = Class.forName(clazz.getClass().getName()).getDeclaredFields();
+ T bean = (T) clazz.newInstance();
+ for (int i = 0; i < fields.length; i++){
+ fields[i].setAccessible(true);
+ String fieldName = fields[i].getName();
+ System.out.println(fieldName);
+ if (fields[i].getGenericType() == String.class) {
+ fields[i].set(String.class,dataJson.getString(fieldName));
+ }
+ if (fields[i].getGenericType() == Integer.class) {
+ fields[i].set(int.class,dataJson.getIntValue(fieldName));
+ }
+ }
+ return bean;
+ }
+ return null;
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("retCode",0);
+ JSONObject innerJson = new JSONObject();
+ innerJson.put("status",1);
+ innerJson.put("statusMsg","运行完成");
+ innerJson.put("url","https://www.baidu.com");
+ innerJson.put("hash","UUIDUtil.getUuid()");
+ jsonObject.put("detail",innerJson);
+ TaskEvData task = dataHandle(jsonObject,TaskEvData.class,"detail");
+ System.out.println(task);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_11_container_with_most_water.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_11_container_with_most_water.java
new file mode 100644
index 0000000..801abeb
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_11_container_with_most_water.java
@@ -0,0 +1,52 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/3 下午4:44
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: ` Given n non-negative integers a1, a2, ..., an ,
+ * ` where each represents a point at coordinate (i, ai).
+ * ` n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0).
+ * ` Find two lines, which together with x-axis forms a container,
+ * ` such that the container contains the most water.
+ *
+ *
+ * ` Note: You may not slant the container and n is at least 2.
+ * ` The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7].
+ * ` In this case, the max area of water (blue section) the container can contain is 49.
+ * `
+ * ` Example:
+ *
+ * ` Input: [1,8,6,2,5,4,8,3,7]
+ * ` Output: 49
+ * @Version: 1.0
+ */
+public class _11_container_with_most_water {
+
+ /**
+ * 这个很简单,也是很经典的问题
+ * 设置两个游标,然后比较两个游标上的容器壁的高度,盛水以矮的为主
+ * 然后移动游标,那边矮就移动哪边
+ *
+ * @param height
+ * @return
+ */
+ public int maxArea(int[] height) {
+ int left = 0;
+ int right = height.length - 1;
+
+ int max = 0;
+ while (left != right) {
+ if (height[left] > height[right]) {
+ max = Math.max(height[right] * (right - left), max);
+ right--;
+ } else {
+ max = Math.max(height[left] * (right - left), max);
+ left++;
+ }
+ }
+ return max;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_120_triangle.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_120_triangle.java
new file mode 100644
index 0000000..8c837f4
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_120_triangle.java
@@ -0,0 +1,77 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 上午9:29
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a triangle, find the minimum path sum from top to bottom.
+ * ` Each step you may move to adjacent numbers on the row below.
+ * ` For example, given the following triangle
+ * `
+ * ` 给定一个三角形,找到从上到下的最小路径总和。
+ * ` 您可以将每一步移至下面一行中的相邻数字。
+ * ` 例如,给定以下三角形
+ * ` [
+ * ` [2],
+ * ` [3,4],
+ * ` [6,5,7],
+ * ` [4,1,8,3]
+ * ` ]
+ * ` The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
+ * @Version: 1.0
+ */
+public class _120_triangle {
+ public static void main(String[] args) {
+ int[][] list = {
+ {2},
+ {3, 4},
+ {6, 5, 7},
+ {4, 1, 8, 3}
+ };
+
+ List> lists = new ArrayList<>();
+ lists.add(Arrays.asList(2));
+ lists.add(Arrays.asList(3, 4));
+ lists.add(Arrays.asList(6, 5, 7));
+ lists.add(Arrays.asList(4, 1, 8, 3));
+ System.out.println(minimumTotal(lists));
+ }
+
+ /**
+ * 动态规划
+ * @param triangle
+ * @return
+ */
+ public static int minimumTotal(List> triangle) {
+
+ int[] ints = new int[triangle.size()];
+ int min = Integer.MAX_VALUE;
+ for (List list : triangle) {
+ // 从右到左,如果从左到右,ints[n-1]会被之前的修改覆盖
+ for (int j = list.size() - 1; j >= 0; j--) {
+ if (j == 0) {
+ ints[0] += list.get(0);
+ } else if (j == list.size() - 1) {
+ ints[j] = list.get(j) + ints[j - 1];
+ } else {
+ ints[j] = list.get(j) + Math.min(ints[j - 1], ints[j]);
+ }
+ }
+ }
+ for (int anInt : ints) {
+ if (min > anInt) {
+ min = anInt;
+ }
+ }
+
+ return min;
+
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_121_best_time_to_buy_and_sell_stock.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_121_best_time_to_buy_and_sell_stock.java
new file mode 100644
index 0000000..51c478c
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_121_best_time_to_buy_and_sell_stock.java
@@ -0,0 +1,53 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 上午10:07
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: `
+ * ` Say you have an array for which the ith element is the price of a given stock on day i.
+ * ` If you were only permitted to complete at most one transaction
+ * ` (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
+ * ` Note that you cannot sell a stock before you buy one.
+ * `
+ * ` 假设您有一个数组,第i个元素是第i天给定股票的价格。
+ * ` 如果您只被允许最多完成一笔交易
+ * ` (即,买入并卖出一股股票),设计一种算法以找到最大的利润。
+ * ` 请注意,您不能在买股票之前卖出股票。
+ * `
+ * ` Example 1:
+ * ` Input: [7,1,5,3,6,4]
+ * ` Output: 5
+ * ` Explanation:
+ * ` Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
+ * ` Not 7-1 = 6, as selling price needs to be larger than buying price.
+ * ` Example 2:
+ * ` Input: [7,6,4,3,1]
+ * ` Output: 0
+ * ` Explanation:
+ * ` In this case, no transaction is done, i.e. max profit = 0.
+ * @Version: 1.0
+ */
+public class _121_best_time_to_buy_and_sell_stock {
+ public static void main(String[] args) {
+ System.out.println(maxProfit(new int[]{7,1,5,3,6,4}));
+ }
+ public static int maxProfit(int[] prices) {
+ if(prices == null || prices.length < 2){
+ return 0;
+ }
+ int buy = prices[0];
+ int profit = 0;
+ for (int i = 1; i < prices.length; i++) {
+ if (buy < prices[i]) {
+ profit = Math.max(prices[i] - buy,profit);
+ } else {
+ buy = prices[i];
+ }
+ }
+
+ return profit;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_122_best_time_to_buy_and_sell_stockII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_122_best_time_to_buy_and_sell_stockII.java
new file mode 100644
index 0000000..575dad6
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_122_best_time_to_buy_and_sell_stockII.java
@@ -0,0 +1,61 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 上午10:23
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Say you have an array prices for which the ith element is the price of a given stock on day i.
+ * ` Design an algorithm to find the maximum profit.
+ * ` You may complete as many transactions as you like
+ * ` (i.e., buy one and sell one share of the stock multiple times).
+ * ` Note: You may not engage in multiple transactions at the same time
+ * ` (i.e., you must sell the stock before you buy again).
+ * ` Example 1:
+ * ` Input: [7,1,5,3,6,4]
+ * ` Output: 7
+ * ` Explanation:
+ * ` Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
+ * ` Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
+ * ` Example 2:
+ * ` Input: [1,2,3,4,5]
+ * ` Output: 4
+ * ` Explanation:
+ * ` Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
+ * ` Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
+ * ` engaging multiple transactions at the same time. You must sell before buying again.
+ * ` Example 3:
+ * ` Input: [7,6,4,3,1]
+ * ` Output: 0
+ * ` Explanation: In this case, no transaction is done, i.e. max profit = 0.
+ * @Version: 1.0
+ */
+public class _122_best_time_to_buy_and_sell_stockII {
+ public static void main(String[] args) {
+ int[] ints = {7, 6, 4, 3, 1};
+ maxProfit(ints);
+ }
+
+ public static int maxProfit(int[] prices) {
+ if (prices == null || prices.length < 2) {
+ return 0;
+ }
+ int profit = 0;
+ int buy = prices[0];
+ for (int i = 1; i < prices.length; i++) {
+ // 只要 后面的大于前面的就继续往后,
+ if (prices[i] > prices[i - 1]) {
+ // 如果是最后一个 如[1,2,3,4,5],当他到5的时候,就要卖出了 不然就是0
+ if (i == prices.length - 1) {
+ profit += prices[i] - buy;
+ }
+ continue;
+ }
+ // 不然就 计算前面的利润 如 [1,2,5,3] 当我们 到 3 的时候,我们就要计算 5-1 的利润
+ profit += prices[i - 1] - buy;
+ buy = prices[i];
+ }
+
+ return profit;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_134_gas_station.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_134_gas_station.java
new file mode 100644
index 0000000..333c05f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_134_gas_station.java
@@ -0,0 +1,99 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 上午9:38
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` There are N gas stations along a circular route,
+ * ` where the amount of gas at station i is gas[i].
+ * ` You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its
+ * next station (i+1).
+ * ` You begin the journey with an empty tank at one of the gas stations.
+ * ` Return the starting gas station's index
+ * ` if you can travel around the circuit once in the clockwise direction, otherwise return -1.
+ * `
+ * ` Note:
+ * ` If there exists a solution, it is guaranteed to be unique.
+ * ` Both input arrays are non-empty and have the same length.
+ * ` Each element in the input arrays is a non-negative integer.
+ * `
+ * ` 沿循环路线有N个加油站,
+ * ` 其中,第i个站点的天然气量为gas [i]。
+ * ` 您有一辆带无限油箱的汽车,从第i站到下一个(i + 1)的行车成本为[i]。
+ * ` 您可以从其中一个加油站的空罐开始旅程。
+ * ` 返回起始加油站的索引
+ * ` 如果您可以沿顺时针方向绕过电路一次,否则返回-1。
+ * ` 注意:
+ * ` 如果存在解决方案,则保证是唯一的。
+ * ` 两个输入数组都是非空的,并且具有相同的长度。
+ * ` 输入数组中的每个元素都是非负整数。
+ * ` Example 1:
+ * ` Input:
+ * ` gas = [1,2,3,4,5]
+ * ` cost = [3,4,5,1,2]
+ * ` Output: 3
+ * ` Explanation:
+ * ` Start at station 3 (index 3) and fill up with 4 unit of gas.
+ * ` Your tank = 0 + 4 = 4 Travel to station 4. Your tank = 4 - 1 + 5 = 8 Travel to station 0.
+ * ` Your tank = 8 - 2 + 1 = 7 Travel to station 1.
+ * ` Your tank = 7 - 3 + 2 = 6 Travel to station 2.
+ * ` Your tank = 6 - 4 + 3 = 5 Travel to station 3.
+ * ` The cost is 5. Your gas is just enough to travel back to station 3.
+ * ` Therefore, return 3 as the starting index.
+ * ` Example 2:
+ * ` Input:
+ * ` gas = [2,3,4]
+ * ` cost = [3,4,3]
+ * ` Output: -1
+ * ` Explanation:
+ * ` You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
+ * ` Let's start at station 2 and fill up with 4 unit of gas.
+ * ` Your tank = 0 + 4 = 4 Travel to station 0.
+ * ` Your tank = 4 - 3 + 2 = 3 Travel to station 1.
+ * ` Your tank = 3 - 3 + 3 = 3 You cannot travel back to station 2, as it requires 4 unit of gas but you
+ * only have 3.
+ * ` Therefore, you can't travel around the circuit once no matter where you start.
+ * @Version: 1.0
+ */
+public class _134_gas_station {
+
+ public static void main(String[] args) {
+
+ int[] gas = {1, 2, 3, 4, 5};
+ int[] cost = {3, 4, 5, 1, 2};
+ System.out.println(canCompleteCircuit(gas, cost));
+ }
+
+ public static int canCompleteCircuit(int[] gas, int[] cost) {
+ int total = 0;
+
+ for (int i = 0; i < gas.length; i++) {
+ total += gas[i] - cost[i];
+ }
+ if (total < 0) {
+ return -1;
+ }
+
+ for (int i = 0; i < gas.length; i++) {
+ if (canDoIt(gas, cost, i)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static boolean canDoIt(int[] gas, int[] cost, int start) {
+ int g = 0;
+ for (int j = 0; j < gas.length; j++) {
+ int position = (j + start) % gas.length;
+ g += gas[position] - cost[position];
+ if (g < 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_138_copy_list_with_random_pointer.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_138_copy_list_with_random_pointer.java
new file mode 100644
index 0000000..fc1e0c9
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_138_copy_list_with_random_pointer.java
@@ -0,0 +1,52 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 上午11:30
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: https://leetcode.com/problems/copy-list-with-random-pointer/
+ * @Version: 1.0
+ */
+public class _138_copy_list_with_random_pointer {
+ public RandomListNode copyRandomList(RandomListNode head) {
+
+ if (head == null) {
+ return null;
+ }
+ Map map = new HashMap<>();
+
+
+
+ RandomListNode node = head;
+ while(node !=null){
+ map.put(node,new RandomListNode(node.val));
+ node = node.next;
+ }
+
+ node = head;
+
+ while(node != null){
+ map.get(node).next = map.get(node.next);
+ map.get(node).random = map.get(node.random);
+ node = node.next;
+ }
+
+ return map.get(head);
+ }
+}
+
+
+class RandomListNode {
+ int val;
+ RandomListNode next;
+ RandomListNode random;
+
+ public RandomListNode(int val) {
+ this.val = val;
+ this.next = null;
+ this.random = null;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_15_3nums.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_15_3nums.java
new file mode 100644
index 0000000..7ee25d1
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_15_3nums.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+
+/**
+ * 题目: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
+ * 注意:答案中不可以包含重复的三元组。
+ *
+ * 实例: 给定数组 nums = [-1, 0, 1, 2, -1, -4],
+ * 满足要求的三元组集合为:
+ * [
+ * [-1, 0, 1],
+ * [-1, -1, 2]
+ * ]
+ *
+ *
+ * 思路:1、将数字从大到小排好序
+ * 2、然后设置两个游标(left,right),只要满足 0-第三个数 == nums[left]-nums[right],
+ * 所以设置 sum=0-第三个数,只要找满足 nums[left]-nums[right] ==sum 即可。
+ * 3、一个从左往右找,一个从右往左找
+ * 4、如果两数之和大于sun,那么说明要找的数字更小,就把右边的游标往左移
+ * 反之,左边的往右移
+ */
+public class _15_3nums {
+
+ public List> threeSum(int[] nums) {
+ if (nums.length < 3) {
+ return new LinkedList<>();
+ }
+ Arrays.sort(nums);
+ List> list = new LinkedList<>();
+ for (int i = 0; i < nums.length - 1; i++) {
+ // 避免添加相同的list
+ if (i == 0 || nums[i] != nums[i - 1]) {
+ int left = i + 1, right = nums.length - 1, sum = -nums[i];
+ while (left < right) {
+ if (nums[left] + nums[right] == sum) {
+ // 添加进列表
+ list.add(Arrays.asList(nums[left], nums[right], nums[i]));
+ // 避免添加相同的list
+ while (left < right && nums[left] == nums[left + 1]) {
+ left++;
+ }
+ while (left < right && nums[right] == nums[right - 1]) {
+ right--;
+ }
+ left++;
+ right--;
+
+ //说明要找的数更大
+ } else if (nums[left] + nums[right] < sum) {
+ left++;
+ } else {
+ //说明要找的数更小
+ right--;
+ }
+ }
+
+ }
+ }
+ return list;
+
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_16_3num_closest.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_16_3num_closest.java
new file mode 100644
index 0000000..3237510
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_16_3num_closest.java
@@ -0,0 +1,61 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.Arrays;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/6 上午10:51
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: ` Given an array nums of n integers and an integer target,
+ * ` find three integers in nums such that the sum is closest to target.
+ * ` Return the sum of the three integers.
+ * ` You may assume that each input would have exactly one solution.
+ * ` Example 1:
+ * ` Input:
+ * ` nums = [-1,2,1,-4], target = 1
+ * ` Output: 2
+ * ` Explanation:
+ * ` The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
+ * @Version: 1.0
+ */
+public class _16_3num_closest {
+ public static void main(String[] args) {
+
+ int[] ints = {1, 2, 4, 8, 16, 32, 64, 128};
+ System.out.println(threeSumClosest(ints, 82));
+ }
+
+ /**
+ * 时间复杂度O(n²)
+ * 设置两个游标,然后进行遍历
+ *
+ * @param nums
+ * @param target
+ * @return
+ */
+ public static int threeSumClosest(int[] nums, int target) {
+ int result = nums[0] + nums[1] + nums[nums.length - 1];
+ int sum;
+ // 先对大小进行排序
+ Arrays.sort(nums);
+ for (int i = 0; i < nums.length; i++) {
+
+ // start 可以跳过之前的。因为之前的已经比较过
+ int start = i + 1, end = nums.length - 1;
+
+ while (start < end) {
+ sum = nums[i] + nums[start] + nums[end];
+
+ if (sum > target) {
+ end--;
+ } else {
+ start++;
+ }
+ if (Math.abs(result - target) > Math.abs(sum - target)) {
+ result = sum;
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_17_letter_combinations_of_a_phone_number.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_17_letter_combinations_of_a_phone_number.java
new file mode 100644
index 0000000..43dfc7f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_17_letter_combinations_of_a_phone_number.java
@@ -0,0 +1,65 @@
+package com.leosanqing.leetcode.medium.array;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/6 上午11:22
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: ` ` Given a string containing digits from 2-9 inclusive,
+ * ` ` return all possible letter combinations that the number could represent.
+ * ` ` A mapping of digit to letters (just like on the telephone buttons) is given below.
+ * ` ` Note that 1 does not map to any letters.
+ * ` ` Example:
+ * ` ` Input: '23'
+ * ` ` Output: ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf'].
+ * @Version: 1.0
+ */
+public class _17_letter_combinations_of_a_phone_number {
+
+ static char[][] num = {
+ {},
+ {},
+ {'a', 'b', 'c'},
+ {'d', 'e', 'f'},
+ {'g', 'h', 'i'},
+ {'j', 'k', 'l'},
+ {'m', 'n', 'o'},
+ {'p', 'q', 'r', 's'},
+ {'t', 'u', 'v'},
+ {'w', 'x', 'y', 'z'}
+ };
+
+ public static void main(String[] args) {
+ System.out.println(JSON.toJSONString(letterCombinations("5465768")));
+ }
+
+ public static List letterCombinations(String digits) {
+ if (digits.length() == 0) {
+ return new ArrayList<>();
+ }
+
+
+ List answer = new ArrayList<>();
+
+ backtrace(answer, 0, new StringBuilder(), digits);
+
+ return answer;
+ }
+
+ private static void backtrace(List answer, int position, StringBuilder sb, String digits) {
+ if (sb.length() == digits.length()) {
+ answer.add(new String(sb));
+ return;
+ }
+
+ for (int j = 0; j < num[digits.charAt(position) - '0'].length; j++) {
+ sb.append(num[digits.charAt(position) - '0'][j]);
+ backtrace(answer, position + 1, sb, digits);
+ sb.deleteCharAt(sb.length() - 1);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_207_courseSchedule.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_207_courseSchedule.java
new file mode 100644
index 0000000..706a577
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_207_courseSchedule.java
@@ -0,0 +1,85 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/17 下午3:57
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: There are a total of numCourses courses you have to take, labeled from 0 to numCourses-1.
+ * Some courses may have prerequisites, for example to take course 0 you have to first take course 1,
+ * which is expressed as a pair: [0,1]
+ * Given the total number of courses and a list of prerequisite pairs,
+ * is it possible for you to finish all courses?
+ *
+ * 您必须参加总共numCourses课程,从0到numCourses-1标记。
+ * 有些课程可能有先决条件,例如,要参加课程0,您必须先参加课程1,表示为一对:[0,1]
+ * 鉴于课程总数和先决条件对列表,您是否可以完成所有课程?
+ *
+ *
+ * Input: numCourses = 2, prerequisites = [[1,0]]
+ * Output: true
+ * Explanation: There are a total of 2 courses to take.
+ * To take course 1 you should have finished course 0. So it is possible.
+ * @Version: 1.0
+ */
+public class _207_courseSchedule {
+
+ public static void main(String[] args) {
+ int[][] courses = {
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {5, 3},
+ {4, 2}
+ };
+
+ System.out.println(canFinish(6, courses));
+
+
+ }
+
+ public static boolean canFinish(int numCourses, int[][] prerequisites) {
+ if (numCourses <= 0) {
+ return false;
+ }
+ Queue queue = new LinkedList<>();
+ int[] inDegree = new int[numCourses];
+ // 因为依赖的课程在第二个位置,所以可以查看有多少个课程依赖了这个课程
+ for (int[] prerequisite : prerequisites) {
+ inDegree[prerequisite[1]]++;
+ }
+
+ // 把最基础的课程(没有其他依赖的)加入队列
+ for (int i = 0; i < inDegree.length; i++) {
+ if (inDegree[i] == 0) {
+ queue.offer(i);
+ }
+ }
+ while (!queue.isEmpty()) {
+ int x = queue.poll();
+ for (int[] prerequisite : prerequisites) {
+ if (x == prerequisite[0]) {
+ inDegree[prerequisite[1]]--;
+ // 如果没有课程依赖了,那么这个课程就要被放入之前的队列中,再次循环
+ if (inDegree[prerequisite[1]] == 0) {
+ queue.offer(prerequisite[1]);
+ }
+ }
+ }
+ }
+
+ // 如果有一个不是0,那么就说明他没有上完
+ for (int value : inDegree) {
+ if (value != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_209_minimumSizeSubarraySum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_209_minimumSizeSubarraySum.java
new file mode 100644
index 0000000..16dd77f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_209_minimumSizeSubarraySum.java
@@ -0,0 +1,62 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/17 下午2:38
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description:
+ * Given an array of n positive integers and a positive integer s,
+ * find the minimal length of a contiguous subarray of which the sum ≥ s.
+ * If there isn't one, return 0 instead.
+ *
+ * 给定一个只有正整数的数组和一个正整数 s
+ * 返回 子数组之和大于 s 的长度
+ * 如果没有,则返回 0
+ *
+ *
+ * Example:
+ *
+ * Input: s = 7, nums = [2,3,1,2,4,3]
+ * Output: 2
+ * Explanation: the subarray [4,3] has the minimal length under the problem constraint.
+ *
+ *
+ *
+ * @Version: 1.0
+ */
+public class _209_minimumSizeSubarraySum {
+
+ public static void main(String[] args) {
+ int a[] = {2,3,1,2,4,3};
+ System.out.println(minSubArrayLen(7,a));
+ }
+
+ /**
+ * 使用滑动窗口,设置两个指针 i 和 j 充当窗口的界限
+ * @param s
+ * @param a
+ * @return
+ */
+ public static int minSubArrayLen(int s, int[] a) {
+ if (a == null || a.length == 0) {
+ return 0;
+ }
+ int i = 0, j = 0, sum = 0;
+ int min = Integer.MAX_VALUE;
+
+ // 在数组范围内
+ while (j < a.length) {
+
+ sum += a[j++];
+ // 如果和大于 s,就从前开始挨个减去
+ while (sum >= s) {
+ min = Math.min(min, j - i);
+ sum -= a[i++];
+ }
+ }
+
+ return min == Integer.MAX_VALUE ? 0 : min;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_210_courseScheduleII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_210_courseScheduleII.java
new file mode 100644
index 0000000..9c46f11
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_210_courseScheduleII.java
@@ -0,0 +1,99 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.*;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/22 下午4:13
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have
+ * prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
+ * Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take
+ * to finish all courses. There may be multiple correct orders, you just need to return one of them. If it is
+ * impossible to finish all courses, return an empty array.
+ * @Version: 1.0
+ *
+ *
+ *
+ *
+ * Example 1:
+ *
+ * Input: 2, [[1,0]]
+ * Output: [0,1]
+ * Explanation: There are a total of 2 courses to take. To take course 1 you should have finished
+ * course 0. So the correct course order is [0,1] .
+ * Example 2:
+ *
+ * Input: 4, [[1,0],[2,0],[3,1],[3,2]]
+ * Output: [0,1,2,3] or [0,2,1,3]
+ * Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both
+ * courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
+ * So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] .
+ */
+public class _210_courseScheduleII {
+
+ public static void main(String[] args) {
+ int[][] courses = {
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {5, 3},
+ {4, 2}
+ };
+
+ canFinish(6, courses);
+
+ }
+
+
+ public static int[] canFinish(int numCourses, int[][] prerequisites) {
+
+
+ int[] answer = new int[numCourses];
+ int cur = numCourses - 1;
+
+
+ if (numCourses <= 0) {
+ return new int[]{};
+ }
+
+ Queue queue = new LinkedList<>();
+ int[] inDegree = new int[numCourses];
+ // 因为依赖的课程在第二个位置,所以可以查看有多少个课程依赖了这个课程
+ for (int[] prerequisite : prerequisites) {
+ inDegree[prerequisite[1]]++;
+ }
+
+ // 把最基础的课程(没有其他依赖的)加入队列
+ for (int i = 0; i < inDegree.length; i++) {
+ if (inDegree[i] == 0) {
+ queue.offer(i);
+ answer[cur--] = i;
+
+ }
+ }
+
+ while (!queue.isEmpty()) {
+ int x = queue.poll();
+ for (int[] prerequisite : prerequisites) {
+ if (x == prerequisite[0]) {
+ inDegree[prerequisite[1]]--;
+ // 如果没有课程依赖了,那么这个课程就要被放入之前的队列中,再次循环
+ if (inDegree[prerequisite[1]] == 0) {
+ queue.offer(prerequisite[1]);
+ answer[cur--] = prerequisite[1];
+ }
+ }
+ }
+ }
+
+ // 如果有一个不是0,那么就说明他没有上完
+ for (int value : inDegree) {
+ if (value != 0) {
+ return new int[]{};
+ }
+ }
+
+ return answer;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_213_houseRobberII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_213_houseRobberII.java
new file mode 100644
index 0000000..1c08918
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_213_houseRobberII.java
@@ -0,0 +1,65 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/2 下午2:20
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description:
+ *` You are a professional robber planning to rob houses along a street.
+ *` Each house has a certain amount of money stashed.
+ *` All houses at this place are arranged in a circle.
+ *` That means the first house is the neighbor of the last one.
+ *` Meanwhile, adjacent houses have security system connected
+ *` and it will automatically contact the police if two adjacent houses were broken into on the same night.
+ *` Given a list of non-negative integers representing the amount of money of each house,
+ *` determine the maximum amount of money you can rob tonight without alerting the police.
+ *
+ *` Example 1:
+ *` Input: [2,3,2]
+ *` Output: 3
+ *` Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2),
+ *` because they are adjacent houses.
+ *
+ *` Example 2:
+ *` Input: [1,2,3,1]
+ *` Output: 4 Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
+ *` Total amount you can rob = 1 + 3 = 4.
+ * @Version: 1.0
+ */
+public class _213_houseRobberII {
+
+ public static void main(String[] args) {
+ _213_houseRobberII houseRobberII = new _213_houseRobberII();
+
+ System.out.println(houseRobberII.rob(new int[]{1,5,4,1,8,7,5,14,8,4}));
+ }
+ public int rob(int[] nums) {
+ if (nums.length == 1) {
+ return nums[0];
+ }
+ return Math.max(rob0(nums), rob1(nums));
+ }
+
+ public int rob0(int[] nums){
+ int preMax = 0, curMax = 0;
+ for(int i = 0; i < nums.length - 1; i++){
+ int t = curMax;
+ curMax = Math.max(preMax + nums[i], curMax);
+ preMax = t;
+ }
+ return curMax;
+ }
+
+ public int rob1(int[] nums){
+ int preMax = 0, curMax = 0;
+ for(int i = 1; i < nums.length; i++){
+ int t = curMax;
+ curMax = Math.max(preMax + nums[i], curMax);
+ preMax = t;
+ }
+ return curMax;
+ }
+
+}
+
+
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_240_search_a_2D_matrixII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_240_search_a_2D_matrixII.java
new file mode 100644
index 0000000..ae3d031
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_240_search_a_2D_matrixII.java
@@ -0,0 +1,75 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午4:12
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Write an efficient algorithm that searches for a value in an m x n matrix.
+ * ` This matrix has the following properties:
+ * ` Integers in each row are sorted in ascending from left to right.
+ * ` Integers in each column are sorted in ascending from top to bottom.
+ * ` Example:
+ * ` Consider the following matrix:
+ * ` [
+ * ` [1, 4, 7, 11, 15],
+ * ` [2, 5, 8, 12, 19],
+ * ` [3, 6, 9, 16, 22],
+ * ` [10, 13, 14, 17, 24],
+ * ` [18, 21, 23, 26, 30]
+ * ` ]
+ * ` Given target = 5, return true.
+ * `
+ * ` Given target = 20, return false.
+ * @Version: 1.0
+ */
+public class _240_search_a_2D_matrixII {
+
+ public static void main(String[] args) {
+
+ int[][] nums = {
+ {1, 5, 7, 9},
+ {1, 4, 7, 11, 15},
+ {2, 5, 8, 12, 19},
+ {3, 6, 9, 16, 22},
+ {10, 13, 14, 17, 24},
+ {18, 21, 23, 26, 30}
+
+ };
+
+ System.out.println(searchMatrix(nums,17));
+}
+
+ /**
+ * 这个题和 74题 很像。只不过这个下面一行不一定大于上面一行的任何一个数
+ * 我们从右上角开始,因为这个是行中最大的,列中最小的
+ * @param matrix
+ * @param target
+ * @return
+ */
+ public static boolean searchMatrix(int[][] matrix, int target) {
+ if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
+ return false;
+ }
+ if (matrix[0][0] > target || matrix[matrix.length - 1][matrix[0].length - 1] < target) {
+ return false;
+ }
+
+ int row = 0;
+ int column = matrix[0].length - 1;
+
+ int num;
+ while (row < matrix.length && column >= 0) {
+ num = matrix[row][column];
+ if (num == target) {
+ return true;
+ }
+ if (num < target) {
+ row++;
+ } else {
+ column--;
+ }
+ }
+ return false;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java
new file mode 100644
index 0000000..6f5fef4
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java
@@ -0,0 +1,111 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/9 下午1:58
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: ` Suppose an array sorted in ascending order is rotated at some pivot unknown to you
+ * beforehand.
+ * ` (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
+ * ` You are given a target value to search.
+ * ` If found in the array return its index, otherwise return -1.
+ * ` You may assume no duplicate exists in the array.
+ * ` Your algorithm's runtime complexity must be in the order of O(log n).
+ *
+ *
+ * ` 假设以升序排序的数组以您不知道的某个枢轴旋转。
+ * ` (即[0,1,2,4,5,6,7]可能会变成[4,5,6,7,0,1,2])。
+ * ` 为您提供了要搜索的目标值。
+ * ` 如果在数组中找到,则返回其索引,否则返回-1。
+ * ` 您可以假设数组中不存在重复项。
+ * ` 算法的运行时复杂度必须为O(log n)的数量级。
+ * `
+ * ` Example 1:
+ * ` Input: nums = [4,5,6,7,0,1,2], target = 0
+ * ` Output: 4
+ * `
+ * ` Example 2:
+ * ` Input: nums = [4,5,6,7,0,1,2], target = 3
+ * ` Output: -1
+ * @Version: 1.0
+ */
+public class _33_search_in_rotated_sorted_array {
+
+ public static void main(String[] args) {
+ int[] nums = new int[]{4, 5, 6, 7, 0, 1, 2};
+ System.out.println(search2(nums, 0));
+ }
+
+ /**
+ * 虽然他不是全部从小到大排序,我们不能用二分法
+ * 但是他有两个部分,两个都是从小到大排序
+ *
+ * @param nums
+ * @param target
+ * @return
+ */
+ public static int search(int[] nums, int target) {
+ if (nums == null || nums.length == 0) {
+ return -1;
+ }
+
+ int left = 0, right = nums.length - 1;
+ while (left <= right) {
+ int mid = left + (right - left) / 2;
+
+ if (target == nums[mid]) {
+ return mid;
+ }
+
+ // 5,7,8,0,1,2,3,4
+ if (nums[left] > nums[mid]) {
+ // target = 7
+ if (target < nums[mid] || nums[left] <= target) {
+ right = mid - 1;
+ } else {
+ // target = 2
+ left = mid + 1;
+ }
+ } else {
+ if (target > nums[mid] || target < nums[left]) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+
+ private static int search2(int[] nums, int target) {
+ if (nums == null || nums.length == 0 || (nums.length == 1 && nums[0] != target)) {
+ return -1;
+ }
+ int left = 0, right = nums.length - 1;
+
+ while (left < right) {
+ int mid = left + (right - left) / 2;
+
+ // 说明 mid 和 target 在同一侧
+ if ((nums[mid] - nums[nums.length - 1]) * (target - nums[nums.length - 1]) > 0) {
+ if (target > nums[mid]) {
+ left = mid + 1;
+ } else {
+ right = mid;
+ }
+ } else if (target - nums[nums.length - 1] > 0) {
+ // target 在左侧
+ right = mid;
+ } else {
+ left = mid + 1;
+ }
+ }
+ if (nums[left] == target) {
+ return left;
+ }
+
+ return -1;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_36_valid_sudoku.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_36_valid_sudoku.java
new file mode 100644
index 0000000..c473d55
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_36_valid_sudoku.java
@@ -0,0 +1,84 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/13 上午11:46
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: ` ` Determine if a 9x9 Sudoku board is valid.
+ * ` ` Only the filled cells need to be validated according to the following rules:
+ * ` ` 1. Each row must contain the digits 1-9 without repetition.
+ * ` ` 2. Each column must contain the digits 1-9 without repetition.
+ * ` ` 3. Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.
+ * 1`
+ * 1`
+ * 1` 确定9x9数独板是否有效。
+ * 1` 仅需根据以下规则验证填充的单元格:
+ * 1` 1.每行必须包含数字1-9,不能重复。
+ * 1` 2.每列必须包含数字1-9,且不能重复。
+ * 1` 3.网格的9个3x3子框中的每个必须包含数字1-9(无重复)。
+ *
+ *
+ * ` Example 1:
+ *
+ * ` Input:
+ * ` [
+ * ` ["5","3",".",".","7",".",".",".","."],
+ * ` ["6",".",".","1","9","5",".",".","."],
+ * ` [".","9","8",".",".",".",".","6","."],
+ * ` ["8",".",".",".","6",".",".",".","3"],
+ * ` ["4",".",".","8",".","3",".",".","1"],
+ * ` ["7",".",".",".","2",".",".",".","6"],
+ * ` [".","6",".",".",".",".","2","8","."],
+ * ` [".",".",".","4","1","9",".",".","5"],
+ * ` [".",".",".",".","8",".",".","7","9"]
+ * ` ]
+ * ` Output: true
+ * ` Example 2:
+ *
+ * ` Input:
+ * ` [
+ * ` ["8","3",".",".","7",".",".",".","."],
+ * ` ["6",".",".","1","9","5",".",".","."],
+ * ` [".","9","8",".",".",".",".","6","."],
+ * ` ["8",".",".",".","6",".",".",".","3"],
+ * ` ["4",".",".","8",".","3",".",".","1"],
+ * ` ["7",".",".",".","2",".",".",".","6"],
+ * ` [".","6",".",".",".",".","2","8","."],
+ * ` [".",".",".","4","1","9",".",".","5"],
+ * ` [".",".",".",".","8",".",".","7","9"]
+ * ` ]
+ * ` Output: false
+ * ` Explanation: Same as Example 1, except with the 5 in the top left corner being
+ * ` modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
+ * ` Note:
+ *
+ * ` A Sudoku board (partially filled) could be valid but is not necessarily solvable.
+ * ` Only the filled cells need to be validated according to the mentioned rules.
+ * ` The given board contain only digits 1-9 and the character '.'.
+ * ` The given board size is always 9x9.
+ * @Version: 1.0
+ */
+public class _36_valid_sudoku {
+ public boolean isValidSudoku(char[][] board) {
+
+ Set set = new HashSet<>();
+ for (int i = 0; i < board.length; i++) {
+ for (int j = 0; j < board.length; j++) {
+ char c = board[i][j];
+ if (c != '.') {
+ if (!set.add(c + "in row" + i) ||
+ !set.add(c + "in column" + j) ||
+ !set.add(c + "in block" + i / 3 + "-" + j/3)
+ ){
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java
new file mode 100644
index 0000000..f8d1d5b
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java
@@ -0,0 +1,73 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/13 下午2:29
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: Given a set of candidate numbers (candidates) (without duplicates) and a target number (target),
+ * find all unique combinations in candidates where the candidate numbers sums to target.
+ * The same repeated number may be chosen from candidates unlimited number of times.
+ *
+ *
+ * 给定一组候选编号(候选)(无重复)和目标编号(target),
+ * 在候选人编号总和为目标的候选人中找到所有唯一组合。
+ * 可以从候选人无限制的次数中选择相同的重复号码。
+ * ` Note:
+ * ` All numbers (including target) will be positive integers.
+ * ` The solution set must not contain duplicate combinations.
+ * ` Example 1:
+ * ` Input: candidates = [2,3,6,7], target = 7,
+ * ` A solution set is: [ [7], [2,2,3] ]
+ * ` Example 2:
+ * ` Input: candidates = [2,3,5], target = 8,
+ * ` A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ]
+ * @Version: 1.0
+ */
+public class _39_combination_sum {
+
+ public static void main(String[] args) {
+ int[] nums = {2, 3, 6, 7};
+
+ combinationSum(nums, 7);
+
+ }
+
+ /**
+ * 这种的做多了,就会发现基本都是一个套路,递归调用
+ *
+ * @param candidates
+ * @param target
+ * @return
+ */
+ public static List> combinationSum(int[] candidates, int target) {
+ List> answer = new ArrayList<>();
+
+ // 先排序
+ Arrays.sort(candidates);
+
+ backtrace(answer, candidates, target, new ArrayList<>(), 0);
+
+ return answer;
+ }
+
+ private static void backtrace(List> answer, int[] candidates, int target, List list, int position) {
+ if (target < 0) {
+ return;
+ }
+
+ if (target == 0) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int i = position; i < candidates.length; i++) {
+ list.add(candidates[i]);
+ backtrace(answer, candidates, target - candidates[i], list, i);
+ list.remove(list.size() - 1);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_40_combination_sumII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_40_combination_sumII.java
new file mode 100644
index 0000000..30ee10b
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_40_combination_sumII.java
@@ -0,0 +1,72 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/13 下午4:04
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1` Given a collection of candidate numbers (candidates) and a target number (target),
+ * 1` find all unique combinations in candidates where the candidate numbers sums to target.
+ * 1` Each number in candidates may only be used once in the combination.
+ * 1` Note:
+ * 1` All numbers (including target) will be positive integers.
+ * 1` The solution set must not contain duplicate combinations.
+ *
+ *
+ * ` 给定一组候选编号(候选)和目标编号(target),
+ * ` 查找候选编号总和为目标的候选中的所有唯一组合。
+ * ` 组合中的每个候选号码只能使用一次。
+ * ` 注:
+ * ` 所有数字(包括目标)将为正整数。
+ * ` 解决方案集不得包含重复的组合。
+ *
+ * 1` Example 1:
+ * 1` Input: candidates = [10,1,2,7,6,1,5], target = 8,
+ * 1` A solution set is: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
+ * 1` Example 2:
+ * 1` Input: candidates = [2,5,2,1,2], target = 5,
+ * 1` A solution set is: [ [1,2,2], [5] ]
+ * @Version: 1.0
+ */
+
+public class _40_combination_sumII {
+
+ public static void main(String[] args) {
+ int[] nums = {10, 1, 2, 7, 6, 1, 5};
+ combinationSum2(nums, 8);
+ }
+
+ public static List> combinationSum2(int[] candidates, int target) {
+
+ Arrays.sort(candidates);
+
+ List> answer = new ArrayList<>();
+
+ backTrace(answer, new ArrayList<>(), candidates, target, 0);
+ return answer;
+ }
+
+ private static void backTrace(List> answer, List list, int[] candidates, int remain,
+ int position) {
+ if (remain < 0) {
+ return;
+ }
+ if (remain == 0) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int i = position; i < candidates.length; i++) {
+ // 去除重复 如 [1,1,2,3]. 去掉第2个1 的结果
+ if (i > position && candidates[i] == candidates[i - 1]) {
+ continue;
+ }
+ list.add(candidates[i]);
+ backTrace(answer, list, candidates, remain - candidates[i], i + 1);
+ list.remove(list.size() - 1);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java
new file mode 100644
index 0000000..de36af7
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java
@@ -0,0 +1,48 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 上午9:36
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a collection of distinct integers, return all possible permutations.
+ * ` Example:
+ * ` Input: [1,2,3]
+ * ` Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
+ * @Version: 1.0
+ */
+public class _46_permutations {
+
+ public static void main(String[] args) {
+ System.out.println(permute(new int[]{1, 2, 3}));
+ }
+
+ public static List> permute(int[] nums) {
+ List> answer = new ArrayList<>();
+
+ backtrace(answer, nums, new ArrayList<>());
+ return answer;
+ }
+
+
+ private static void backtrace(List> answer, int[] nums, List list) {
+ if (list.size() == nums.length) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int num : nums) {
+ if (list.contains(num)) {
+ continue;
+ }
+
+ list.add(num);
+ backtrace(answer, nums, list);
+ list.remove(list.size() - 1);
+ }
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_47_permutationsII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_47_permutationsII.java
new file mode 100644
index 0000000..3236178
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_47_permutationsII.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 上午10:08
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a collection of numbers that might contain duplicates,
+ * ` return all possible unique permutations.
+ * ` Example:
+ * ` Input: [1,1,2]
+ * ` Output: [ [1,1,2], [1,2,1], [2,1,1] ]
+ * @Version: 1.0
+ */
+public class _47_permutationsII {
+
+ public static void main(String[] args) {
+ System.out.println(permute(new int[]{1, 1, 3}));
+
+ }
+
+ public static List> permute(int[] nums) {
+ List> answer = new ArrayList<>();
+
+ if (nums == null || nums.length == 0) {
+ return answer;
+ }
+ Arrays.sort(nums);
+ boolean[] used = new boolean[nums.length];
+
+ backTrace(answer, new ArrayList<>(), nums, used);
+ return answer;
+
+ }
+
+ /**
+ * 递归遍历
+ *
+ * @param answer
+ * @param list
+ * @param nums
+ */
+ private static void backTrace(List> answer, List list, int[] nums, boolean[] used) {
+ if (list.size() == nums.length) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+ for (int i = 0; i < nums.length; i++) {
+ // 如果有这个数字,就跳过. 并且排除 相邻相同的数字两种情况。之前的排序就为了这个
+ if (used[i] || (i > 0 && nums[i - 1] == nums[i] && !used[i - 1])) {
+ continue;
+ }
+ list.add(nums[i]);
+ used[i] = true;
+ backTrace(answer, list, nums, used);
+ list.remove(list.size() - 1);
+ used[i] = false;
+
+ }
+
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java
new file mode 100644
index 0000000..807d56d
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java
@@ -0,0 +1,109 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 上午10:32
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * `` You are given an n x n 2D matrix representing an image.
+ * `` Rotate the image by 90 degrees (clockwise).
+ * `` Note:
+ * `` You have to rotate the image in-place,
+ * `` which means you have to modify the input 2D matrix directly.
+ * `` DO NOT allocate another 2D matrix and do the rotation.
+ * `` Example 1:
+ * `` Given input matrix =
+ * `` [
+ * `` [1,2,3],
+ * `` [4,5,6],
+ * `` [7,8,9]
+ * `` ],
+ * `` rotate the input matrix in-place such that it becomes:
+ * `` [
+ * `` [7,4,1],
+ * `` [8,5,2],
+ * `` [9,6,3]
+ * `` ]
+ * `` Example 2:
+ * `` Given input matrix =
+ * `` [
+ * `` [ 5, 1, 9,11],
+ * `` [ 2, 4, 8,10],
+ * `` [13, 3, 6, 7],
+ * `` [15,14,12,16]
+ * `` ],
+ * `` rotate the input matrix in-place such that it becomes:
+ * `` [
+ * `` [15,13, 2, 5],
+ * `` [14, 3, 4, 1],
+ * `` [12, 6, 8, 9],
+ * `` [16, 7,10,11]
+ * `` ]
+ * @Version: 1.0
+ */
+public class _48_rotate_image {
+ public static void main(String[] args) {
+
+ }
+
+
+ /**
+ * 分成两步进行旋转
+ *
+ * 1 2 3
+ * 4 5 6
+ * 7 8 9
+ *
+ * 1 4 7
+ * 2 5 8
+ * 3 6 9
+ *
+ * 7 4 1
+ * 8 5 2
+ * 9 6 3
+ *
+ * @param matrix
+ */
+ public static void rotate(int[][] matrix) {
+ int temp;
+
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = i; j < matrix[0].length; j++) {
+ temp = matrix[i][j];
+ matrix[i][j] = matrix[j][i];
+ matrix[j][i] = temp;
+ }
+ }
+
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < matrix.length / 2; j++) {
+ temp = matrix[i][j];
+ matrix[i][j] = matrix[i][matrix.length - 1 - j];
+ matrix[i][matrix.length - 1 - j] = temp;
+ }
+ }
+ }
+
+
+ public static void rotate1(int[][] matrix) {
+ int temp;
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = i; j < matrix[0].length; j++) {
+ if (i == j) {
+ continue;
+ }
+ temp = matrix[i][j];
+ matrix[i][j] = matrix[j][i];
+ matrix[j][i] = temp;
+ }
+ }
+
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < matrix[0].length / 2; j++) {
+ temp = matrix[i][j];
+ matrix[i][j] = matrix[i][matrix[0].length - j - 1];
+ matrix[i][matrix[0].length - j - 1] = temp;
+ }
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java
new file mode 100644
index 0000000..ef9489a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.*;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 下午2:18
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` ` Given an array of strings, group anagrams together.
+ * ` ` 给定一个字符串数组,将字谜分组在一起。
+ * ` ` Example:
+ * ` ` Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
+ * ` ` Output:
+ * ` ` [
+ * ` ` ["ate","eat","tea"],
+ * ` ` ["nat","tan"],
+ * ` ` ["bat"]
+ * ` ` ]
+ * @Version: 1.0
+ */
+public class _49_group_anagrams {
+
+ public static void main(String[] args) {
+ String[] strings = {"eat", "tea", "tan", "ate", "nat", "bat"};
+ System.out.println(groupAnagrams(strings));
+ }
+
+ public static List> groupAnagrams(String[] strs) {
+ List> answer = new ArrayList<>();
+
+ if (strs == null || strs.length == 0) {
+ return answer;
+ }
+
+ Map> map = new HashMap<>();
+
+ for (String str : strs) {
+ char[] chars = new char[26];
+ for (char c : str.toCharArray()) {
+ chars[c - 'a']++;
+ }
+ String s = Arrays.toString(chars);
+
+ List list = map.getOrDefault(s, new ArrayList<>());
+ list.add(str);
+ map.put(s, list);
+
+ }
+ return new ArrayList<>(map.values());
+
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_54_spiral_matrix.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_54_spiral_matrix.java
new file mode 100644
index 0000000..4042a96
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_54_spiral_matrix.java
@@ -0,0 +1,87 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 下午2:57
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` ` Given a matrix of m x n elements (m rows, n columns),
+ * ` ` return all elements of the matrix in spiral order.
+ * ` ` 给定一个由m x n个元素组成的矩阵(m行n列),
+ * ` ` 以螺旋顺序返回矩阵的所有元素。
+ * ` ` Example 1:
+ * ` ` Input:
+ * ` ` [
+ * ` ` [ 1, 2, 3 ],
+ * ` ` [ 4, 5, 6 ],
+ * ` ` [ 7, 8, 9 ]
+ * ` ` ]
+ * ` ` Output: [1,2,3,6,9,8,7,4,5]
+ * ` ` Example 2:
+ * ` ` Input:
+ * ` ` [
+ * ` ` [1, 2, 3, 4],
+ * ` ` [5, 6, 7, 8],
+ * ` ` [9,10,11,12]
+ * ` ` ]
+ * ` ` Output: [1,2,3,4,8,12,11,10,9,5,6,7]
+ * @Version: 1.0
+ */
+public class _54_spiral_matrix {
+ public static void main(String[] args) {
+
+ int[][] ints = {
+ {1,2,3,4},
+ {5,6,7,8},
+ {9,10,11,12}
+ };
+
+ spiralOrder(ints);
+ }
+
+
+ public static List spiralOrder(int[][] matrix) {
+ List list = new ArrayList<>();
+
+
+ if (matrix == null || matrix.length == 0) {
+ return list;
+ }
+
+ int left = 0, top = 0,
+ right = matrix[0].length - 1, bottom = matrix.length - 1;
+
+
+ while (list.size() < matrix[0].length * matrix.length) {
+ for (int i = left; i <= right; i++) {
+ list.add(matrix[top][i]);
+ }
+ top++;
+
+ for (int i = top; i <= bottom; i++) {
+ list.add(matrix[i][right]);
+ }
+ right--;
+
+ for (int i = right; i >= left; i--) {
+ list.add(matrix[bottom][i]);
+ }
+ bottom--;
+
+ for (int i = bottom; i >= top; i--){
+ list.add(matrix[i][left]);
+ }
+ left++;
+ }
+
+ while(list.size()!= matrix.length * matrix[0].length){
+ list.remove(list.size()-1);
+ }
+ return list;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java
new file mode 100644
index 0000000..a274d72
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java
@@ -0,0 +1,66 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 下午3:32
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` ` Given an array of non-negative integers,
+ * ` ` you are initially positioned at the first index of the array.
+ * ` ` Each element in the array represents your maximum jump length at that position.
+ * ` ` Determine if you are able to reach the last index.
+ * ` `
+ * ` ` 给定一个非负整数数组,
+ * ` ` 您最初位于数组的第一个索引。
+ * ` ` 数组中的每个元素代表该位置的最大跳转长度。
+ * ` ` 确定您是否能够达到最后一个索引。
+ * ` ` Example 1:
+ * ` ` Input: nums = [2,3,1,1,4]
+ * ` ` Output: true
+ * ` ` Explanation:
+ * ` ` Jump 1 step from index 0 to 1, then 3 steps to the last index.
+ * ` ` Example 2:
+ * ` ` Input: nums = [3,2,1,0,4]
+ * ` ` Output: false
+ * ` ` Explanation:
+ * ` ` You will always arrive at index 3 no matter what.
+ * ` ` Its maximum jump length is 0, which makes it impossible to reach the last index.
+ * @Version: 1.0
+ */
+public class _55_jump_game {
+ public static void main(String[] args) {
+ System.out.println(canJump(new int[]{3, 2, 1, 1, 4}));
+
+ System.out.println(canJump(new int[]{3, 2, 1, 0, 4}));
+ }
+
+
+ /**
+ * The basic idea is this: at each step, we keep track of the furthest reachable index. The nature of the problem
+ * (eg. maximal jumps where you can hit a range of targets instead of singular jumps where you can only hit one
+ * target) is that for an index to be reachable, each of the previous indices have to be reachable.
+ *
+ * Hence, it suffices that we iterate over each index, and If we ever encounter an index that is not reachable,
+ * we abort and return false. By the end, we will have iterated to the last index. If the loop finishes, then the
+ * last index is reachable.
+ *
+ * 基本思想是:在每个步骤中,我们都跟踪最远的可到达索引。
+ * 问题的性质(例如,您可以击中一个目标范围的最大跳跃,而不是您只能击中一个目标的奇异跳跃)是要使一个索引可以到达,必须使每个先前的索引都可以到达。
+ *
+ * 因此,我们迭代每个索引就足够了,如果遇到无法访问的索引,我们将中止并返回false。到最后,我们将迭代到最后一个索引。如果循环结束,则最后一个索引可达。
+ *
+ * @param nums
+ * @return
+ */
+ public static boolean canJump(int[] nums) {
+ int max = 0;
+ for (int i = 0; i < nums.length; i++) {
+ if (i > max) {
+ return false;
+ }
+ // 算出能到达的最远距离
+ max = Math.max(max, i + nums[i]);
+ }
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java
new file mode 100644
index 0000000..4343b06
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/14 下午4:23
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a collection of intervals, merge all overlapping intervals.
+ * ` Example 1:
+ * ` Input: [[1,3],[2,6],[8,10],[15,18]]
+ * ` Output: [[1,6],[8,10],[15,18]]
+ * ` Explanation:
+ * ` Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
+ * ` Example 2:
+ * ` Input: [[1,4],[4,5]]
+ * ` Output: [[1,5]]
+ * ` Explanation: Intervals [1,4] and [4,5] are considered overlapping.
+ * @Version: 1.0
+ */
+public class _56_merge_intervals {
+ /**
+ * 先对给定的数组进行排列
+ * @param intervals
+ * @return
+ */
+ public static int[][] merge(int[][] intervals) {
+ // 先排序
+ Arrays.sort(intervals, Comparator.comparingInt(i -> i[0]));
+
+ List answer = new ArrayList<>();
+
+ for (int[] interval : intervals) {
+ int left = interval[0];
+ int right = interval[1];
+
+ if (answer.isEmpty()) {
+ answer.add(new int[]{left, right});
+ continue;
+ }
+
+ if (answer.get(answer.size() - 1)[1] < left) {
+ answer.add(new int[]{left, right});
+ } else {
+ answer.get(answer.size() - 1)[1] = Math.max(answer.get(answer.size() - 1)[1], right);
+ }
+ }
+ return answer.toArray(new int[answer.size()][]);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_59_spiral_matrixII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_59_spiral_matrixII.java
new file mode 100644
index 0000000..02f20af
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_59_spiral_matrixII.java
@@ -0,0 +1,57 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/15 下午5:14
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a positive integer n,
+ * ` generate a square matrix filled with elements from 1 to n2 in spiral order.
+ * ` Example:
+ * ` Input: 3
+ * ` Output:
+ * ` [
+ * ` [ 1, 2, 3 ],
+ * ` [ 8, 9, 4 ],
+ * ` [ 7, 6, 5 ]
+ * ` ]
+ * @Version: 1.0
+ */
+public class _59_spiral_matrixII {
+
+ public static void main(String[] args) {
+ System.out.println(generateMatrix(4));
+ }
+
+ public static int[][] generateMatrix(int n) {
+ if (n < 1) {
+ return new int[][]{};
+ }
+ int[][] result = new int[n][n];
+ int left = 0, right = n - 1, top = 0, bottom = n - 1;
+ int count = 1;
+ while (count <= n*n) {
+ for (int i = left; i <= right; i++, count++) {
+ result[top][i] = count;
+ }
+ top++;
+
+ for (int i = top; i <= bottom; i++, count++) {
+ result[i][right] = count;
+ }
+ right--;
+
+ for (int i = right; i >= left; i--, count++) {
+ result[bottom][i] = count;
+ }
+ bottom--;
+
+ for (int i = bottom; i >= top; i--, count++) {
+ result[i][left] = count;
+ }
+ left++;
+ }
+
+ return result;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java
new file mode 100644
index 0000000..b1dc68a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java
@@ -0,0 +1,64 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 上午9:47
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
+ * ` The robot can only move either down or right at any point in time.
+ * ` The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
+ * ` How many possible unique paths are there?
+ * ` Above is a 7 x 3 grid. How many possible unique paths are there?
+ * `
+ * ` 机器人位于m x n网格的左上角(在下图中标记为“开始”)。
+ * ` 机器人只能在任何时间点上下移动。
+ * ` 机器人试图到达网格的右下角(在下图中标记为“完成”)。
+ * ` 有多少可能的唯一路径?
+ * ` 上面是7 x 3的网格。有多少种可能的独特路径?
+ * ` Example 1:
+ * ` Input: m = 3, n = 2
+ * ` Output: 3
+ * ` Explanation:
+ * ` From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
+ * ` 1. Right -> Right -> Down
+ * ` 2. Right -> Down -> Right
+ * ` 3. Down -> Right -> Right
+ * ` Example 2:
+ * ` Input: m = 7, n = 3
+ * ` Output: 28
+ * @Version: 1.0
+ */
+public class _62_unique_paths {
+ public static void main(String[] args) {
+ System.out.println(uniquePaths(3, 3));
+ System.out.println(uniquePaths(3, 7));
+ }
+
+ /**
+ * 使用动态规划,机器人只能向下或者向右,所以当前到当前坐标的可能性就是 上边坐标的可能性加上左边坐标的可能性
+ *
+ * @param m
+ * @param n
+ * @return
+ */
+ public static int uniquePaths(int m, int n) {
+ int[] pre = new int[m];
+ int[] cur = new int[m];
+
+ for (int i = 0; i < m; i++) {
+ cur[i] = 1;
+ pre[i] = 1;
+ }
+
+ for (int i = 1; i < m; i++) {
+ for (int j = 1; j < n; j++) {
+ cur[j] = cur[j - 1] + pre[j];
+ }
+ pre = cur;
+ }
+
+ return cur[m - 1];
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_63_unique_pathsII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_63_unique_pathsII.java
new file mode 100644
index 0000000..56838ea
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_63_unique_pathsII.java
@@ -0,0 +1,87 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 上午10:12
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
+ * ` The robot can only move either down or right at any point in time.
+ * ` The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
+ * ` Now consider if some obstacles are added to the grids. How many unique paths would there be?
+ * ` An obstacle and empty space is marked as 1 and 0 respectively in the grid.
+ * `
+ * ` Note: m and n will be at most 100.
+ * ` Example 1:
+ * ` Input:
+ * ` [
+ * ` [0,0,0],
+ * ` [0,1,0],
+ * ` [0,0,0]
+ * ` ]
+ * ` Output: 2
+ * ` Explanation:
+ * ` There is one obstacle in the middle of the 3x3 grid above.
+ * ` There are two ways to reach the bottom-right corner:
+ * ` 1. Right -> Right -> Down -> Down
+ * ` 2. Down -> Down -> Right -> Right
+ * @Version: 1.0
+ */
+public class _63_unique_pathsII {
+ public static void main(String[] args) {
+ int[][] obstacleGrid = new int[][]{
+ {0, 0, 0},
+ {0, 1, 0},
+ {0, 0, 0,}
+ };
+ System.out.println(uniquePathsWithObstacles(obstacleGrid));
+ }
+
+ /**
+ * 思路和 62题 很像,只不过做些特殊处理
+ *
+ * @param obstacleGrid
+ * @return
+ */
+ public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
+ if (obstacleGrid == null || obstacleGrid.length == 0 || obstacleGrid[0].length == 0) {
+ return 0;
+ }
+
+ int rows = obstacleGrid.length;
+ int columns = obstacleGrid[0].length;
+
+ int[] pre = new int[columns];
+ int[] cur = new int[columns];
+ // 先设置第一行
+ for (int i = 0; i < columns; i++) {
+ if (obstacleGrid[0][0] == 1) {
+ return 0;
+ }
+
+ if (obstacleGrid[0][i] == 1) {
+ break;
+ }
+ pre[i] = 1;
+ cur[i] = 1;
+ }
+
+ // 处理第二行之后的
+ for (int i = 1; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ // 处理 障碍物
+ if (obstacleGrid[i][j] == 1) {
+ cur[j] = 0;
+ continue;
+ }
+ if (j != 0) {
+ cur[j] = cur[j - 1] + pre[j];
+ }
+ }
+
+ pre = cur;
+ }
+
+ return cur[columns - 1];
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java
new file mode 100644
index 0000000..d57c29a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java
@@ -0,0 +1,55 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/16 下午4:50
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a m x n grid filled with non-negative numbers,
+ * ` find a path from top left to bottom right which minimizes the sum of all numbers along its path.
+ * ` Note:
+ * ` You can only move either down or right at any point in time.
+ * ` Example:
+ * ` Input:
+ * ` [
+ * ` [1,3,1],
+ * ` [1,5,1],
+ * ` [4,2,1]
+ * ` ]
+ * ` Output: 7
+ * ` Explanation: Because the path 1→3→1→1→1 minimizes the sum.
+ * @Version: 1.0
+ */
+public class _64_minimum_path_sum {
+ public static void main(String[] args) {
+ int[][] ints = {
+ {1, 3, 1, 1},
+ {1, 5, 12, 1},
+ {4, 2, 10, 2},
+ {1, 1, 1, 10}
+ };
+
+ System.out.println(minPathSum(ints));
+ }
+
+
+ private static int minPathSum(int[][] grid) {
+ for (int i = 1; i < grid.length; i++) {
+ grid[i][0] += grid[i - 1][0];
+ }
+
+ for (int i = 1; i < grid[0].length; i++) {
+ grid[0][i] += grid[0][i - 1];
+ }
+
+ for (int i = 1; i < grid.length; i++) {
+ for (int j = 1; j < grid[0].length; j++) {
+ grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]);
+ }
+ }
+
+ return grid[grid.length - 1][grid[0].length - 1];
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_73_set_matrix_zeroes.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_73_set_matrix_zeroes.java
new file mode 100644
index 0000000..8f239d6
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_73_set_matrix_zeroes.java
@@ -0,0 +1,75 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 上午11:22
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ *` ` Given a m x n matrix, if an element is 0, set its entire row and column to 0.
+ *` ` Do it in-place.
+ *` ` Example 1:
+ *` ` Input:
+ *` ` [
+ *` ` [1,1,1],
+ *` ` [1,0,1],
+ *` ` [1,1,1]
+ *` ` ]
+ *` ` Output:
+ *` ` [
+ *` ` [1,0,1],
+ *` ` [0,0,0],
+ *` ` [1,0,1]
+ *` ` ]
+ *` ` Example 2:
+ *` ` Input:
+ *` ` [
+ *` ` [0,1,2,0],
+ *` ` [3,4,5,2],
+ *` ` [1,3,1,5]
+ *` ` ]
+ *` ` Output:
+ *` ` [
+ *` ` [0,0,0,0],
+ *` ` [0,4,5,0],
+ *` ` [0,3,1,0]
+ *` ` ]
+ * @Version: 1.0
+ */
+public class _73_set_matrix_zeroes {
+ public static void main(String[] args) {
+ int[][] matrix = new int[][]{
+ {1,1,1},
+ {1,0,1},
+ {1,1,1}
+ };
+ setZeroes(matrix);
+ }
+ public static void setZeroes(int[][] matrix) {
+ if (matrix == null) {
+ return;
+ }
+ boolean row[] = new boolean[matrix.length];
+ boolean column[] = new boolean[matrix[0].length];
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < matrix[0].length; j++) {
+ if(matrix[i][j] == 0){
+ row[i] = true;
+ column[j] = true;
+ }
+ }
+ }
+
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < matrix[0].length; j++) {
+ if(row[i]){
+ matrix[i][j] = 0;
+ }
+ if(column[j]){
+ matrix[i][j] = 0;
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_74_search_a_2D_matrix.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_74_search_a_2D_matrix.java
new file mode 100644
index 0000000..a73150e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_74_search_a_2D_matrix.java
@@ -0,0 +1,95 @@
+package com.leosanqing.leetcode.medium.array;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午2:40
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Write an efficient algorithm that searches for a value in an m x n matrix.
+ * ` This matrix has the following properties:
+ * ` Integers in each row are sorted from left to right.
+ * ` The first integer of each row is greater than the last integer of the previous row.
+ * `
+ * ` 编写一种有效的算法,在m x n矩阵中搜索值。
+ * ` 该矩阵具有以下属性:
+ * ` 每行中的整数从左到右排序。
+ * ` 每行的第一个整数大于前一行的最后一个整数。
+ * ` Example 1:
+ * ` Input: matrix =
+ * ` [
+ * ` [1, 3, 5, 7],
+ * ` [10, 11, 16, 20],
+ * ` [23, 30, 34, 50]
+ * ` ]
+ * ` target = 3
+ * ` Output: true
+ * ` Example 2:
+ * ` Input:
+ * ` matrix = [
+ * ` [1, 3, 5, 7],
+ * ` [10, 11, 16, 20],
+ * ` [23, 30, 34, 50]
+ * ` ] target = 13
+ * ` Output: false
+ * @Version: 1.0
+ */
+public class _74_search_a_2D_matrix {
+ public static void main(String[] args) {
+ int[][] ints = {
+ {1, 3, 5, 7},
+ {10, 11, 16, 21},
+ {22, 25, 27, 30},
+ {35, 44, 56, 70}
+ };
+
+ int[][] nums = {{1,3}};
+ System.out.println(searchMatrix(nums,2));
+
+ System.out.println(searchMatrix(ints, 1));
+ System.out.println(searchMatrix(ints, 16));
+ System.out.println(searchMatrix(ints, 27));
+ System.out.println(searchMatrix(ints, 44));
+
+ }
+
+ /**
+ * 把它不当成矩阵,当成一个排好序的列表
+ * @param matrix
+ * @param target
+ * @return
+ */
+ public static boolean searchMatrix(int[][] matrix, int target) {
+ if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
+ return false;
+ }
+
+ int m = matrix.length;
+ int n = matrix[0].length;
+ if (matrix[0][0] > target || matrix[m - 1][n - 1] < target) {
+ return false;
+ }
+
+ int start = 0;
+ int end = m * n - 1;
+ int mid = (end - start) / 2 + start;
+ int num = Integer.MIN_VALUE;
+ while (start <= end) {
+ num = matrix[mid / n][mid % n];
+ if (num == target) {
+ return true;
+ }
+
+ if (num < target) {
+ start = mid + 1;
+ } else {
+ end = mid - 1;
+ }
+ mid = (end - start) / 2 + start;
+ }
+
+ return false;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java
new file mode 100644
index 0000000..4a90260
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java
@@ -0,0 +1,70 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午7:21
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given an array with n objects colored red, white or blue,
+ * ` sort them in-place so that objects of the same color are adjacent,
+ * ` with the colors in the order red, white and blue.
+ * ` Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
+ * ` Note: You are not suppose to use the library's sort function for this problem.
+ * ` Example:
+ * ` Input: [2,0,2,1,1,0]
+ * ` Output: [0,0,1,1,2,2]
+ * @Version: 1.0
+ */
+public class _75_sort_colors {
+ public static void main(String[] args) {
+ sortColors(new int[]{2, 0, 2, 1, 1, 0});
+ }
+
+ public static void sortColors(int[] nums) {
+ int n2 = -1, n1 = -1, n0 = -1;
+
+ for (int i = 0; i < nums.length; i++) {
+ if (nums[i] == 0) {
+ nums[++n2] = 2;
+ nums[++n1] = 1;
+ nums[++n0] = 0;
+ } else if (nums[i] == 1) {
+ nums[++n2] = 2;
+ nums[++n1] = 1;
+ } else if (nums[i] == 2) {
+ nums[++n2] = 2;
+ }
+
+ }
+ }
+
+
+ /**
+ * 使用两个指针,p1指向0,p2指向2
+ * 然后遍历,找到0就和 P1上的数字交换,找到2就和p2上的数字交换
+ *
+ * 但是这个时候有一个情况是,2交换后仍可能是2
+ * 参考 0 2 1 2 1 0 2 自己手动交换一下就知道,所以才有 while里面的内容
+ * @param nums
+ */
+ public static void sortColors1(int[] nums) {
+ int n1 = 0;
+ int n2 = nums.length - 1;
+
+ for (int i = 0; i <= n2; i++) {
+ // 交换过后 此时 nums[i] 可能是 0,也可能是2 ,还需要再继续交换
+ while (i <= n2 && nums[i] == 2) {
+ int temp = nums[i];
+ nums[i] = nums[n2];
+ nums[n2] = temp;
+ --n2;
+ }
+ if (nums[i] == 0) {
+ int temp = nums[i];
+ nums[i] = nums[n1];
+ nums[n1] = temp;
+ ++n1;
+ }
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java
new file mode 100644
index 0000000..ff5adfd
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java
@@ -0,0 +1,93 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/21 上午9:07
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a 2D board and a word, find if the word exists in the grid.
+ * ` The word can be constructed from letters of sequentially adjacent cell,
+ * ` where "adjacent" cells are those horizontally or vertically neighboring.
+ * ` The same letter cell may not be used more than once.
+ * ` 给定一个2D板和一个单词,查找单词是否存在于网格中。
+ * ` 该单词可以由顺序相邻的单元格的字母构成,
+ * ` 其中“相邻”单元是水平或垂直相邻的单元。
+ * ` 同一字母单元不得重复使用。
+ * ` Example:
+ * ` board = [
+ * ` ['A','B','C','E'],
+ * ` ['S','F','C','S'],
+ * ` ['A','D','E','E']
+ * ` ]
+ * ` Given word = "ABCCED", return true.
+ * ` Given word = "SEE", return true.
+ * ` Given word = "ABCB", return false.
+ * @Version: 1.0
+ */
+public class _79_word_search {
+
+
+ public static void main(String[] args) {
+
+ char[][] board = {
+ {'A', 'B', 'C', 'E'},
+ {'S', 'F', 'C', 'S'},
+ {'A', 'D', 'E', 'E'}
+ };
+
+
+ System.out.println(exist(board, "ABCCED"));
+ System.out.println(exist(board, "SEE"));
+ System.out.println(exist(board, "ABCB"));
+ }
+
+ public static boolean exist(char[][] board, String word) {
+
+ boolean[][] isUsed = new boolean[board.length][board[0].length];
+
+ for (int i = 0; i < board.length; i++) {
+ for (int j = 0; j < board[0].length; j++) {
+ if(backtrace(board, word, i, j, 0, isUsed)){
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean backtrace(char[][] board, String word, int x, int y, int index, boolean[][] isUsed) {
+
+ // 超出边界
+ if (x > board.length - 1 || y > board[0].length - 1 || x < 0 || y < 0) {
+ return false;
+ }
+
+ if (isUsed[x][y]) {
+ return false;
+ }
+
+ if (board[x][y] != word.charAt(index)) {
+ return false;
+ }
+
+ isUsed[x][y] = true;
+ if (index == word.length() - 1) {
+ return true;
+ }
+
+ if (
+ backtrace(board, word, x + 1, y, index + 1, isUsed)
+ || backtrace(board, word, x - 1, y, index + 1, isUsed)
+ || backtrace(board, word, x, y - 1, index + 1, isUsed)
+ || backtrace(board, word, x, y + 1, index + 1, isUsed)
+ ) {
+ return true;
+ }
+
+ isUsed[x][y] = false;
+
+ return false;
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_81_search_in_rotated_sorted_arrayII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_81_search_in_rotated_sorted_arrayII.java
new file mode 100644
index 0000000..ee7d776
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_81_search_in_rotated_sorted_arrayII.java
@@ -0,0 +1,67 @@
+package com.leosanqing.leetcode.medium.array;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/21 上午11:40
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
+ * (i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).
+ * You are given a target value to search.
+ * If found in the array return true, otherwise return false.
+ * Example 1:
+ * Input: nums = [2,5,6,0,0,1,2], target = 0
+ * Output: true
+ * Example 2:
+ * Input: nums = [2,5,6,0,0,1,2], target = 3
+ * Output: false
+ * @Version: 1.0
+ */
+public class _81_search_in_rotated_sorted_arrayII {
+
+ public static void main(String[] args) {
+ System.out.println(search(new int[]{4, 5, 6, 7, 0, 1, 2}, 0));
+ }
+
+
+ public static boolean search(int[] nums, int target) {
+ if (nums == null || nums.length == 0) {
+ return false;
+ }
+ int start = 0, end = nums.length - 1;
+
+ int mid = (end - start) / 2 + start;
+
+ while (start <= end) {
+ if (nums[mid] == target || nums[start] == target || nums[end] == target) {
+ return true;
+ }
+
+ // 说明 mid 没有越过分割点,那么中点左边部分是排好序的
+ if (nums[mid] > nums[start]) {
+ // 如果 target 比左边点小 或者 比 中点大,那么 我们可以确定这个点 肯定不在 左边
+ if (nums[mid] < target || target < nums[start]) {
+ start = mid;
+ } else {
+ end = mid;
+ }
+ } else if (nums[mid] < nums[start]) {
+ // 如果 target 比 中点小 或者 比 最右边的大,那么 target 肯定在 中点左侧
+ if (nums[mid] > target || target > nums[end]) {
+ end = mid;
+ } else {
+ start = mid;
+ }
+ } else {
+ start++;
+ }
+
+ mid = (end - start) / 2 + start;
+
+ }
+
+ return false;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java
new file mode 100644
index 0000000..ac96f93
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java
@@ -0,0 +1,62 @@
+package com.leosanqing.leetcode.medium.array;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/22 下午3:00
+ * @Package: com.leosanqing.leetcode.medium.array
+ * @Description: 1
+ * ` Given a collection of integers that might contain duplicates, nums, return all possible subsets (the
+ * power set).
+ * ` Note: The solution set must not contain duplicate subsets.
+ * ` Example:
+ * ` Input: [1,2,2]
+ * ` Output: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]
+ * @Version: 1.0
+ */
+public class _90_subsetsII {
+
+ public static void main(String[] args) {
+
+ System.out.println(JSON.toJSONString(subsetsWithDup(new int[]{1, 2, 2})));
+ }
+
+ public static List> subsetsWithDup(int[] nums) {
+ if (nums == null) {
+ return null;
+ }
+ List> answer = new ArrayList<>();
+
+ // 先排序
+ Arrays.sort(nums);
+ for (int i = 0; i <= nums.length; i++) {
+ backTrace(answer, new ArrayList<>(), nums, 0, i);
+ }
+
+ return answer;
+ }
+
+ private static void backTrace(List> answer, List list, int[] nums, int position, int max) {
+
+ if (list.size() == max) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int i = position; i < nums.length; i++) {
+ if (i > position && nums[i] == nums[i - 1]) {
+ continue;
+ }
+ list.add(nums[i]);
+ backTrace(answer, list, nums, i + 1, max);
+ list.remove(list.size() - 1);
+ }
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/ListNode.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/ListNode.java
new file mode 100644
index 0000000..ce488ce
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/ListNode.java
@@ -0,0 +1,21 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @author zhuerchong
+ */
+public class ListNode {
+ public int val;
+ public ListNode next;
+
+ public ListNode() {
+ }
+
+ public ListNode(int val) {
+ this.val = val;
+ }
+
+ public ListNode(int val, ListNode next) {
+ this.val = val;
+ this.next = next;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_137_single_numberII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_137_single_numberII.java
new file mode 100644
index 0000000..62bcbb8
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_137_single_numberII.java
@@ -0,0 +1,45 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 下午5:29
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ *` Given a non-empty array of integers,
+ *` every element appears three times except for one,
+ *` which appears exactly once. Find that single one.
+ *` Note: Your algorithm should have a linear runtime complexity.
+ *` Could you implement it without using extra memory?
+ *` Example 1:
+ *` Input: [2,2,3,2]
+ *` Output: 3
+ *` Example 2:
+ *` Input: [0,1,0,1,0,1,99]
+ *` Output: 99
+ *`
+ * @Version: 1.0
+ */
+public class _137_single_numberII {
+ public static void main(String[] args) {
+ int[] ints = {2,2,3,2};
+ System.out.println(singleNumber(ints));
+ }
+
+ public static int singleNumber(int[] nums) {
+ int ans = 0;
+ for(int i = 0; i < 32; i++) {
+ int sum = 0;
+ for (int num : nums) {
+ if (((num >> i) & 1) == 1) {
+ sum++;
+ sum %= 3;
+ }
+ }
+ if(sum != 0) {
+ ans |= sum << i;
+ }
+ }
+ return ans;
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java
new file mode 100644
index 0000000..472e9d3
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java
@@ -0,0 +1,47 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 下午4:50
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a linked list, return the node where the cycle begins.
+ * ` If there is no cycle, return null.
+ * ` To represent a cycle in the given linked list,
+ * ` we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to.
+ * ` If pos is -1, then there is no cycle in the linked list.
+ * ` Note: Do not modify the linked list.
+ * ` Example 1:
+ * ` Input: head = [3,2,0,-4], pos = 1
+ * ` Output: tail connects to node index 1
+ * ` Explanation:
+ * ` There is a cycle in the linked list, where tail connects to the second node.
+ * ` Example 2:
+ * ` Input: head = [1,2], pos = 0
+ * ` Output: tail connects to node index 0
+ * ` Explanation:
+ * ` There is a cycle in the linked list, where tail connects to the first node.
+ * @Version: 1.0
+ */
+public class _142_linked_list_cycleII {
+
+ public ListNode detectCycle(ListNode head) {
+ ListNode slow = head;
+ ListNode fast = head;
+
+ while (fast != null && fast.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+
+ if (slow == fast) {
+ ListNode n = head;
+ while (slow != n) {
+ slow = slow.next;
+ n = n.next;
+ }
+ return n;
+ }
+ }
+ return null;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_143_reorder_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_143_reorder_list.java
new file mode 100644
index 0000000..1859da6
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_143_reorder_list.java
@@ -0,0 +1,93 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 下午5:03
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a singly linked list L: L0→L1→…→Ln-1→Ln,
+ * ` reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
+ * ` You may not modify the values in the list's nodes, only nodes itself may be changed.
+ * ` 给定一个单链表L:L0→L1→…→Ln-1→Ln,
+ * ` 将其重新排序为:L0→Ln→L1→Ln-1→L2→Ln-2→…
+ * ` 您不能修改列表节点中的值,只能更改节点本身。
+ * ` Example 1:
+ * ` Given 1->2->3->4,
+ * ` reorder it to 1->4->2->3.
+ * ` Example 2:
+ * ` Given 1->2->3->4->5,
+ * ` reorder it to 1->5->2->4->3.
+ * @Version: 1.0
+ */
+public class _143_reorder_list {
+ public static void main(String[] args) {
+ ListNode listNode = new ListNode(1);
+ listNode.next = new ListNode(2);
+ listNode.next.next = new ListNode(3);
+ listNode.next.next.next = new ListNode(4);
+// listNode.next.next.next.next = new ListNode(5);
+// listNode.next.next.next.next.next = new ListNode(6);
+
+ reorderList(listNode);
+ }
+
+ /**
+ * 分三步完成
+ * 1. 找到中点
+ * 2. 反转中点后的节点
+ * 3. 然后挨个进行重组
+ *
+ * @param head
+ */
+ public static void reorderList(ListNode head) {
+
+ if (head == null) {
+ return;
+ }
+ // 1。找到中点
+ ListNode fakeNode = new ListNode();
+ fakeNode.next = head;
+ ListNode fast = fakeNode;
+ ListNode slow = fakeNode;
+ while (fast != null && fast.next != null) {
+ fast = fast.next.next;
+ slow = slow.next;
+ }
+
+
+ // 2. 反转中点之后的节点 1 -> 2 -> 3 -> 4 -> 5 -> 6 变成 1 -> 2 -> 3 -> 6 -> 5 -> 4
+ ListNode slowNext = reverse(slow.next);
+
+ // 3. 重组 1 -> 2 -> 3 -> 6 -> 5 -> 4 变成 1 -> 6 -> 2 -> 5 -> 3 -> 4
+
+ slow = head;
+ ListNode firstNext;
+ fast = slowNext;
+ ListNode secondNext;
+ while (slow.next != null && fast != null) {
+ secondNext = fast.next;
+ firstNext = slow.next;
+ fast.next = slow.next;
+ slow.next = fast;
+ fast = secondNext;
+ slow = firstNext;
+ }
+
+ slow.next = null;
+ System.out.println();
+
+ }
+
+ private static ListNode reverse(ListNode node) {
+
+ if (node == null || node.next == null) {
+ return node;
+ }
+ ListNode next = reverse(node.next);
+
+ node.next.next = node;
+ node.next = null;
+ return next;
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java
new file mode 100644
index 0000000..8f3a2ba
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java
@@ -0,0 +1,51 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/7 下午3:47
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: Given a linked list, remove the n-th node from the end of list and return its head.
+ *
+ *
+ * ` `Example:
+ * ` ` Give linked list: 1->2->3->4->5, and n = 2.
+ * ` ` After removing the second node from the end, the linked list becomes
+ * ` ` 1->2->3->5.
+ * ` ` Note: Given n will always be valid.
+ * @Version: 1.0
+ */
+public class _19_remove_Nth_node_from_end_of_list {
+
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 思路就是使用两个节点,一个快节点先走 n步,然后快节点走到最后,后面的那个节点就是我们要去掉的节点
+ * 设置一个虚拟头结点,可以帮助我们解决边界值问题
+ *
+ * @param head
+ * @param n
+ * @return
+ */
+ public ListNode removeNthFromEnd(ListNode head, int n) {
+ ListNode fakeHead = new ListNode();
+
+ ListNode slow = fakeHead;
+ ListNode fast = fakeHead;
+
+ fakeHead.next = head;
+
+ for (int i = 0; i < n; i++) {
+ fast = fast.next;
+ }
+
+ while (fast.next != null) {
+ fast = fast.next;
+ slow = slow.next;
+ }
+ slow.next = slow.next.next;
+
+ return fakeHead.next;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_24_swap_nodes_in_pairs.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_24_swap_nodes_in_pairs.java
new file mode 100644
index 0000000..7e66fa0
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_24_swap_nodes_in_pairs.java
@@ -0,0 +1,57 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/9 上午10:25
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: ` Given a linked list, swap every two adjacent nodes and return its head.
+ * ` You may not modify the values in the list's nodes, only nodes itself may be changed.
+ * ` Example:
+ * ` Given 1->2->3->4,
+ * ` you should return the list as 2->1->4->3.
+ * @Version: 1.0
+ */
+public class _24_swap_nodes_in_pairs {
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(5);
+ ListNode node2 = new ListNode(2, node1);
+ ListNode node3 = new ListNode(6, node2);
+ ListNode node4 = new ListNode(1, node3);
+
+ ListNode x = swapPairs(node4);
+
+ while (x != null) {
+ System.out.println(x.val);
+ x= x.next;
+ }
+ }
+
+
+ public static ListNode swapPairs(ListNode head) {
+
+ if (head == null) {
+ return null;
+ }
+ ListNode fakeHead = new ListNode();
+ fakeHead.next = head;
+
+ ListNode root = fakeHead;
+ ListNode pre = head;
+ ListNode curr = pre.next;
+
+ while (pre.next != null) {
+ root.next = pre.next;
+ pre.next = curr.next;
+ curr.next = pre;
+
+ root = curr.next;
+ if (pre.next == null) {
+ return fakeHead.next;
+ }
+ curr = pre.next.next;
+ pre = root.next;
+ }
+ return fakeHead.next;
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java
new file mode 100644
index 0000000..888c5d4
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java
@@ -0,0 +1,72 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/2 下午4:54
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: ` ` You are given two non-empty linked lists representing two non-negative integers.
+ * ` ` The digits are stored in reverse order and each of their nodes contain a single digit.
+ * ` ` Add the two numbers and return it as a linked list.
+ * ` ` You may assume the two numbers do not contain any leading zero, except the number 0 itself.
+ *
+ * ` ` 您将获得两个表示两个非负整数的非空链表。
+ * ` ` 这些数字以相反的顺序存储,并且它们的每个节点都包含一个数字。
+ * ` ` 将两个数字相加并作为链接列表返回。
+ * ` ` 您可以假设两个数字除了数字0本身以外,都不包含任何前导零。
+ *
+ * ` ` Example:
+ * ` ` Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
+ * ` ` Output: 7 -> 0 -> 8
+ * ` ` Explanation: 342 + 465 = 807.
+ * @Version: 1.0
+ */
+public class _2_addTwoNumbers {
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(5);
+ ListNode node2 = new ListNode(2, node1);
+ ListNode node3 = new ListNode(6, node2);
+ ListNode node4 = new ListNode(5);
+ ListNode node5 = new ListNode(1, node4);
+ ListNode node6 = new ListNode(3, node5);
+
+ ListNode listNode1 = addTwoNumbers(node3, node6);
+ }
+
+ public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
+
+ ListNode cur1 = l1;
+ ListNode cur2 = l2;
+
+ ListNode head = new ListNode();
+ ListNode cur = head;
+
+ int carry = 0;
+ // 定义在这里不需要新建对象
+ int sum;
+
+ while (cur1 != null || cur2 != null) {
+ if (cur1 == null) {
+ cur1 = new ListNode(0);
+ }
+ if (cur2 == null) {
+ cur2 = new ListNode(0);
+ }
+
+ // 计算位数之和
+ sum = carry + cur1.val + cur2.val;
+ // 是否大于0
+ carry = sum / 10;
+ cur.next = new ListNode(sum % 10);
+
+ cur = cur.next;
+ cur1 = cur1.next;
+ cur2 = cur2.next;
+ }
+
+ if (carry != 0) {
+ cur.next = new ListNode(1);
+ }
+ return head.next;
+ }
+}
+
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_77_combinations.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_77_combinations.java
new file mode 100644
index 0000000..065360e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_77_combinations.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.medium.list;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午7:44
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
+ * ` 给定两个整数n和k,返回1 ... n中k个数字的所有可能组合。
+ * ` Example:
+ * ` Input: n = 4, k = 2
+ * ` Output: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
+ * @Version: 1.0
+ */
+public class _77_combinations {
+ public static void main(String[] args) {
+
+ combine(4, 2);
+ }
+
+ public static List> combine(int n, int k) {
+
+ if (n == 0 || k <= 0) {
+
+ return new ArrayList<>();
+ }
+ List> answer = new ArrayList<>();
+
+ backTrace(answer, new ArrayList<>(), k, n, 1);
+
+ return answer;
+ }
+
+
+ public static void backTrace(List> answer, List list, int k, int n, int position) {
+
+ if (list.size() == k) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int i = position; i <= n; i++) {
+ if (list.contains(i)) {
+ continue;
+ }
+ list.add(i);
+ backTrace(answer, list, k, n, i + 1);
+ list.remove(list.size() - 1);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java
new file mode 100644
index 0000000..0bffeea
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java
@@ -0,0 +1,53 @@
+package com.leosanqing.leetcode.medium.list;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午8:08
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a set of distinct integers, nums, return all possible subsets (the power set).
+ * ` Note: The solution set must not contain duplicate subsets.
+ * ` Example:
+ * ` Input: nums = [1,2,3]
+ * ` Output: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
+ * @Version: 1.0
+ */
+public class _78_subsets {
+ public static void main(String[] args) {
+ System.out.println(JSON.toJSONString(subsets(new int[]{1, 2, 3})));
+ }
+
+ /**
+ * 这个真的太经典了,回溯的经典题型,你会发现有很多很多这种的题
+ *
+ * @param nums
+ * @return
+ */
+ public static List> subsets(int[] nums) {
+ List> answer = new ArrayList<>();
+
+ for (int i = 0; i <= nums.length; i++) {
+ backtrace(answer, new ArrayList<>(), i, nums, 0);
+ }
+
+ return answer;
+ }
+
+ private static void backtrace(List> answer, List list, int max, int[] nums, int position) {
+ if (list.size() == max) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+ for (int i = position; i < nums.length; i++) {
+ list.add(nums[i]);
+ backtrace(answer, list, max, nums, i + 1);
+ list.remove(list.size() - 1);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_82_remove_duplicates_from_sorted_listII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_82_remove_duplicates_from_sorted_listII.java
new file mode 100644
index 0000000..f5f2e62
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_82_remove_duplicates_from_sorted_listII.java
@@ -0,0 +1,68 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/21 下午4:48
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a sorted linked list, delete all nodes that have duplicate numbers,
+ * ` leaving only distinct numbers from the original list.
+ * ` Return the linked list sorted as well.
+ * ` Example 1:
+ * ` Input: 1->2->3->3->4->4->5
+ * ` Output: 1->2->5
+ * ` Example 2:
+ * ` Input: 1->1->1->2->3
+ * ` Output: 2->3
+ * @Version: 1.0
+ */
+public class _82_remove_duplicates_from_sorted_listII {
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(4);
+ ListNode node2 = new ListNode(4, node1);
+ ListNode node3 = new ListNode(3, node2);
+ ListNode node4 = new ListNode(2,node3);
+ ListNode node5 = new ListNode(2, node4);
+ ListNode node6 = new ListNode(2, node5);
+ ListNode node7 = new ListNode(1, node6);
+
+ deleteDuplicates(node7);
+ }
+
+ public static ListNode deleteDuplicates(ListNode head) {
+ if (head == null) {
+ return null;
+ }
+ ListNode fakeNode = new ListNode();
+ fakeNode.next = head;
+
+ ListNode pre = fakeNode;
+ ListNode cur = fakeNode.next;
+ ListNode next = cur.next;
+ while (next != null) {
+ if(next.val != cur.val){
+ pre = cur;
+ cur = next;
+ next = cur.next;
+ continue;
+ }
+ // 一直找到不重复的
+ while(next != null && cur.val == next.val){
+ cur = next;
+ next = next.next;
+ }
+ // 然后把 之前的 pre 节点直接链接到 next节点。这样中间重复的就相当于被删除了
+ if (next != null){
+ pre.next = next;
+ cur = next;
+ next = cur.next;
+ }else{
+ pre.next = next;
+ }
+
+
+ }
+
+ return fakeNode.next;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_83_remove_duplicates_from_sorted_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_83_remove_duplicates_from_sorted_list.java
new file mode 100644
index 0000000..e4b1efc
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_83_remove_duplicates_from_sorted_list.java
@@ -0,0 +1,50 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/21 下午5:28
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ *` Given a sorted linked list, delete all duplicates such that each element appear only once.
+ *` Example 1:
+ *` Input: 1->1->2
+ *` Output: 1->2
+ *` Example 2:
+ *` Input: 1->1->2->3->3
+ *` Output: 1->2->3
+ * @Version: 1.0
+ */
+public class _83_remove_duplicates_from_sorted_list {
+ public static void main(String[] args) {
+ ListNode node1 = new ListNode(1);
+ ListNode node2 = new ListNode(1, node1);
+ ListNode node3 = new ListNode(1, node2);
+ ListNode node4 = new ListNode(1,node3);
+ ListNode node5 = new ListNode(1, node4);
+ ListNode node6 = new ListNode(1, node5);
+ ListNode node7 = new ListNode(1, node6);
+
+ System.out.println(deleteDuplicates(node7).val);
+ }
+
+ public static ListNode deleteDuplicates(ListNode head) {
+ ListNode fakeNode = new ListNode(Integer.MIN_VALUE);
+ fakeNode.next = head;
+
+ ListNode pre = fakeNode;
+ ListNode cur = pre.next;
+
+
+ while (cur != null){
+ if(pre.val == cur.val){
+ cur = cur.next;
+ pre.next = cur;
+ continue;
+ }
+ pre = cur;
+ cur = cur.next;
+ }
+
+ return fakeNode.next;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java
new file mode 100644
index 0000000..c5d337c
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.medium.list;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/1 下午7:01
+ * @Package: com.leosanqing.leetcode.medium
+ * @Description: Reverse a linked list from position m to n. Do it in one-pass.
+ * 对反转给定范围的链表节点进行反转,只遍历一遍
+ *
+ * Note: 1 ≤ m ≤ n ≤ length of list.
+ *
+ * Example:
+ *
+ * Input: 1->2->3->4->5->NULL, m = 2, n = 4
+ * Output: 1->4->3->2->5->NULL
+ * @Version: 1.0
+ */
+public class _92_reverseLinkedList2 {
+
+ public ListNode reverseBetween(ListNode head, int m, int n) {
+ if (head == null) {
+ return null;
+ }
+ // 设置一个虚拟头结点
+ ListNode fakeHead = new ListNode(0);
+ fakeHead.next = head;
+ ListNode cur1 = fakeHead;
+ ListNode pre1 = null;
+
+ // 找到 m 的位置
+ for (int i = 0; i < m; i++) {
+ pre1 = cur1;
+ cur1 = cur1.next;
+ }
+
+ ListNode next;
+ ListNode pre2 = pre1;
+ ListNode cur2 = cur1;
+ for (int i = 0; i <= n - m; i++) {
+ next = cur2.next;
+ cur2.next = pre2;
+ pre2 = cur2;
+ cur2 = next;
+ }
+
+ // 反转完之后,链接 m 之前的节点 和 n 后的节点
+ pre1.next = pre2;
+ cur1.next = cur2;
+
+ return fakeHead.next;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/num/_264_uglyNumberII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/num/_264_uglyNumberII.java
new file mode 100644
index 0000000..3c024da
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/num/_264_uglyNumberII.java
@@ -0,0 +1,52 @@
+package com.leosanqing.leetcode.medium.num;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/23 下午4:17
+ * @Package: com.leosanqing.leetcode.medium.num
+ * @Description: Write a program to find the n-th ugly number.
+ * Ugly numbers are positive numbers whose prime factors
+ * only include 2, 3, 5.
+ * @Version: 1.0
+ *
+ *
+ * Example:
+ *
+ * Input: n = 10
+ * Output: 12
+ * Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
+ * Note:
+ *
+ * 1 is typically treated as an ugly number.
+ * n does not exceed 1690.
+ */
+public class _264_uglyNumberII {
+ public int nthUglyNumber(int n) {
+
+ // 创建一个数组,用来存储 uglyNumber
+ int[] ugly = new int[n];
+ ugly[0] = 1;
+
+ int index2 = 0, index3 = 0, index5 = 0;
+ int factor2 = 2, factor3 = 3, factor5 = 5;
+ for (int i = 1; i < n; i++) {
+ int min = Math.min(Math.min(factor2, factor3), factor5);
+ ugly[i] = min;
+ // 如果 这个数字是他的倍数,那就往后走,
+ // 比如 30 是 2 3 5 的共同的 uglyNumber,所以他们都要往后移一个
+ if (factor2 == min) {
+ factor2 = 2 * ugly[++index2];
+ }
+ if (factor3 == min) {
+ factor3 = 3 * ugly[++index3];
+ }
+ if (factor5 == min) {
+ factor5 = 5 * ugly[++index5];
+ }
+ }
+ return ugly[n - 1];
+ }
+
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_131_palindrome_partitioning.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_131_palindrome_partitioning.java
new file mode 100644
index 0000000..1b29a54
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_131_palindrome_partitioning.java
@@ -0,0 +1,58 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 下午5:43
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * ` Given a string s, partition s such that every substring of the partition is a palindrome.
+ * ` Return all possible palindrome partitioning of s.
+ * ` Example:
+ * ` Input: "aab"
+ * ` Output:
+ * ` [
+ * ` ["aa","b"],
+ * ` ["a","a","b"]
+ * ` ]
+ * @Version: 1.0
+ */
+public class _131_palindrome_partitioning {
+ public static void main(String[] args) {
+ partition("aab");
+ }
+ public static List> partition(String s) {
+
+ List> answer = new ArrayList<>();
+ for (int i = 1; i < s.length(); i++) {
+ backTrace(answer,new ArrayList<>(), s, 0, i);
+ }
+ return answer;
+ }
+
+ private static void backTrace(List> answer, List list, String s, int position, int length) {
+ if (position >= s.length()) {
+ answer.add(new ArrayList<>(list));
+ return;
+ }
+
+
+ String substring = s.substring(position, position + length);
+ if (isPalindrome(substring)) {
+ list.add(substring);
+ return;
+ }
+ backTrace(answer, list, s, position + length, length);
+ }
+
+ private static boolean isPalindrome(String s) {
+ for (int i = 0; i < s.length() / 2; i++) {
+ if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java
new file mode 100644
index 0000000..b16fbac
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java
@@ -0,0 +1,80 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/4 上午11:38
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * 1 Given a non-empty string s and a dictionary wordDict containing a list of non-empty words,
+ * 1 determine if s can be segmented into a space-separated sequence of one or more dictionary words.
+ * 1 给定一个非空字符串s和一个包含非空单词列表的字典wordDict,
+ * 1 确定是否可以将s分割为一个或多个词典单词的以空格分隔的序列
+ * 1
+ * 1 Note:
+ * 1 The same word in the dictionary may be reused multiple times in the segmentation.
+ * 1 You may assume the dictionary does not contain duplicate words.
+ * 1 Example 1:
+ * 1 Input: s = "leetcode", wordDict = ["leet", "code"]
+ * 1 Output: true
+ * 1 Explanation:
+ * 1 Return true because "leetcode" can be segmented as "leet code".
+ * 1 Example 2:
+ * 1 Input: s = "applepenapple", wordDict = ["apple", "pen"]
+ * 1 Output: true
+ * 1 Explanation:
+ * 1 Return true because "applepenapple" can be segmented as "apple pen apple".
+ * 1 Note that you are allowed to reuse a dictionary word.
+ * 1 Example 3:
+ * 1 Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
+ * 1 Output: false
+ * 1
+ * @Version: 1.0
+ */
+public class _139_word_break {
+
+ static Set set;
+
+ public static void main(String[] args) {
+ String s = "leetcode";
+
+ System.out.println(wordBreak(s, Arrays.asList("leet", "code")));
+ }
+
+ public static boolean wordBreak(String s, List wordDict) {
+ set = new HashSet<>(wordDict);
+ return backtrace(s, 0, new HashSet<>());
+
+ }
+
+
+ private static boolean backtrace(String s, int position, Set words) {
+ if (position == s.length()) {
+ return true;
+ }
+
+ // 如果存在,则说明已经尝试过这种方法,就直接返回
+ if (words.contains(position)) {
+ return false;
+ }
+
+ for (int i = position + 1; i <= s.length(); i++) {
+ if (!set.contains(s.substring(position, i))) {
+ continue;
+ }
+
+ if (backtrace(s, i, words)) {
+ return true;
+ }
+
+ words.add(i);
+ }
+
+ words.add(position);
+ return false;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java
new file mode 100644
index 0000000..2b746b8
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java
@@ -0,0 +1,60 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/8 下午3:44
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: ` Given n pairs of parentheses, write a function to generate all combinations of well-formed
+ * parentheses.
+ * `
+ * ` For example,
+ * ` given n = 3, a solution set is:
+ * ` [
+ * ` "((()))",
+ * ` "(()())",
+ * ` "(())()",
+ * ` "()(())",
+ * ` "()()()"
+ * ` ]
+ * @Version: 1.0
+ */
+public class _22_generate_parentheses {
+
+
+ public static void main(String[] args) {
+ System.out.println(generateParenthesis(3));
+ }
+
+ public static List generateParenthesis(int n) {
+ List list = new ArrayList<>();
+
+ backtrace(list, new StringBuilder(), 0, 0, n);
+
+ return list;
+ }
+
+
+ private static void backtrace(List result, StringBuilder sb, int left, int right, int max) {
+ if (left == max && right == max) {
+ result.add(sb.toString());
+ return;
+ }
+
+ if (left <= max) {
+ sb.append("(");
+ backtrace(result, sb, left + 1, right, max);
+ sb.deleteCharAt(sb.length() - 1);
+ }
+
+ // 避免出现 ())这种情况
+ if (right < left) {
+ sb.append(")");
+ backtrace(result, sb, left, right + 1, max);
+ sb.deleteCharAt(sb.length() - 1);
+ }
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java
new file mode 100644
index 0000000..ecdabb3
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java
@@ -0,0 +1,70 @@
+package com.leosanqing.leetcode.medium.string;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.Arrays;
+
+/**
+ * @description: ` 实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
+ * `
+ * ` 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
+ * `
+ * ` 必须 原地 修改,只允许使用额外常数空间。
+ * `
+ * ` 示例 1:
+ * `
+ * ` 输入:nums = [1,2,3]
+ * ` 输出:[1,3,2]
+ * ` 示例 2:
+ * `
+ * ` 输入:nums = [3,2,1]
+ * ` 输出:[1,2,3]
+ * ` 示例 3:
+ * `
+ * ` 输入:nums = [1,1,5]
+ * ` 输出:[1,5,1]
+ * ` 示例 4:
+ * `
+ * ` 输入:nums = [1]
+ * ` 输出:[1]
+ * @author: rtliu
+ * @date: 2021/4/8 2:07 下午
+ */
+public class _31_next_permutation {
+ public static void main(String[] args) {
+ nextPermutation(new int[]{1, 3, 2});
+ }
+
+ /**
+ * 1.从右到左找升序数字
+ * 2.找到右边比当前数字大的数字,两个交换位置
+ * 3.右边数字再重新升序排列
+ *
+ * @param nums
+ */
+ public static void nextPermutation(int[] nums) {
+
+ for (int i = nums.length - 1; i > 0; i--) {
+ if (nums[i] < nums[i - 1]) {
+ continue;
+ }
+
+ for (int j = nums.length - 1; j >= i; j--) {
+ if (nums[i - 1] > nums[j]) {
+ continue;
+ }
+
+ // 从后面找比 num 大的数字,交换
+ int temp = nums[i - 1];
+ nums[i - 1] = nums[j];
+ nums[j] = temp;
+
+ Arrays.sort(nums, i, nums.length);
+ return;
+
+ }
+
+ }
+ Arrays.sort(nums);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java
new file mode 100644
index 0000000..9f0589e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java
@@ -0,0 +1,66 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description: Given a string s, find the length of the longest substring without repeating characters.
+ *
+ * 给定字符串s,找到最长子字符串的长度而不重复字符。
+ *
+ * ` Example 1:
+ *
+ * ` Input: s = "abcabcbb"
+ * ` Output: 3
+ * ` Explanation: The answer is "abc", with the length of 3.
+ * ` Example 2:
+ *
+ * ` Input: s = "bbbbb"
+ * ` Output: 1
+ * ` Explanation: The answer is "b", with the length of 1.
+ * ` Example 3:
+ *
+ * ` Input: s = "pwwkew"
+ * ` Output: 3
+ * ` Explanation: The answer is "wke", with the length of 3.
+ * ` Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
+ * ` Example 4:
+ *
+ * ` Input: s = ""
+ * ` Output: 0
+ *
+ * ` @author: rtliu
+ * ` @date: 2021/4/6 3:41 下午
+ */
+public class _3_longest_substring_without_repeating_characters {
+ public static void main(String[] args) {
+ System.out.println(lengthOfLongestSubstring("abba"));
+ }
+
+ /**
+ * 这个是典型的滑动窗口类的题型
+ *
+ * 我们遇到相同的字符就丢弃之前字符左边的所有字符
+ * @param s
+ * @return
+ */
+ public static int lengthOfLongestSubstring(String s) {
+ Map map = new HashMap<>(s.length() * 2);
+
+ int result = 0;
+ int head = 0;
+
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+
+ if (map.containsKey(c) && head < map.get(c)) {
+ head = map.get(c);
+ }
+ // i+1 表示当前字符的实际位置
+ result = Math.max(i + 1 - head, result);
+ map.put(c, i + 1);
+ }
+
+ return result;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_43_multiply_strings.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_43_multiply_strings.java
new file mode 100644
index 0000000..4e191d8
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_43_multiply_strings.java
@@ -0,0 +1,63 @@
+package com.leosanqing.leetcode.medium.string;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/13 下午5:05
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * ` Given two non-negative integers num1 and num2 represented as strings,
+ * ` return the product of num1 and num2, also represented as a string.
+ * `
+ * ` 给定两个表示为字符串的非负整数num1和num2,
+ * ` 返回num1和num2的乘积,也表示为字符串。
+ * ` Example 1:
+ * ` Input: num1 = "2", num2 = "3"
+ * ` Output: "6"
+ * ` Example 2:
+ * ` Input: num1 = "123", num2 = "456"
+ * ` Output: "56088"
+ * @Version: 1.0
+ */
+public class _43_multiply_strings {
+ public static void main(String[] args) {
+
+ System.out.println(multiply("999", "999").equals(String.valueOf(999 * 999)));
+
+ }
+
+ /**
+ * 我们做乘法也是这样做
+ * @param num1
+ * @param num2
+ * @return
+ */
+ public static String multiply(String num1, String num2) {
+
+ int m = num1.length();
+ int n = num2.length();
+
+ int[] result = new int[m + n];
+
+ for (int i = m - 1; i >= 0; i--) {
+ for (int j = n - 1; j >= 0; j--) {
+ int temp = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
+ int p1 = i + j, p2 = i + j + 1;
+
+ int sum = temp + result[p2];
+
+ result[p1] += sum / 10;
+ result[p2] = sum % 10;
+
+ }
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i : result) {
+ if (stringBuilder.length() == 0 && i == 0) {
+ continue;
+ }
+ stringBuilder.append(i);
+ }
+ return stringBuilder.length() == 0 ? "0" : stringBuilder.toString();
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java
new file mode 100644
index 0000000..464db5c
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java
@@ -0,0 +1,56 @@
+package com.leosanqing.leetcode.medium.string;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/3 上午11:16
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: ` ` Given a string s, find the longest palindromic substring in s.
+ * ` ` You may assume that the maximum length of s is 1000.
+ * `
+ * ` ` 给定字符串s,找到s中最长的回文子字符串。
+ * ` 您可以假设s的最大长度为1000。
+ * ` ` Example 1:
+ * ` ` Input: "babad"
+ * ` ` Output: "bab"
+ * ` ` Note: "aba" is also a valid answer.
+ * ` ` Example 2:
+ * ` ` Input: "cbbd"
+ * ` ` Output: "bb"
+ * @Version: 1.0
+ */
+public class _5_longestPalindromicSubstring {
+ public static void main(String[] args) {
+ String s = "abasasaiug";
+ System.out.println(longestPalindrome(s));
+ }
+
+ public static String longestPalindrome(String s) {
+ if (s.length() < 2) {
+ return s;
+ }
+ String longStr = "";
+
+ for (int i = 0; i < s.length(); i++) {
+ String s1 = findStr(s, i, i);
+ String s2 = findStr(s, i, i + 1);
+
+ if (s1.length() > longStr.length()) {
+ longStr = s1;
+ }
+ if (s2.length() > longStr.length()) {
+ longStr = s2;
+ }
+ }
+
+ return longStr;
+ }
+
+ private static String findStr(String s, int i, int j) {
+ for (; i >= 0 && j < s.length(); i--, j++) {
+ if (s.charAt(i) != s.charAt(j)) {
+ break;
+ }
+ }
+ return s.substring(i + 1, j);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_71_simplify_path.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_71_simplify_path.java
new file mode 100644
index 0000000..417c455
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_71_simplify_path.java
@@ -0,0 +1,90 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Stack;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/20 下午1:56
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * ` Given an absolute path for a file (Unix-style), simplify it.
+ * ` Or in other words, convert it to the canonical path.
+ * ` In a UNIX-style file system, a period .
+ * ` refers to the current directory. Furthermore, a double period .. moves the directory up a level.
+ * `
+ * ` Note that the returned canonical path must always begin with a slash /,
+ * ` and there must be only a single slash / between two directory names.
+ * ` The last directory name (if it exists) must not end with a trailing /.
+ * ` Also, the canonical path must be the shortest string representing the absolute path.
+ * `
+ * ` 给定文件的绝对路径(Unix风格),请简化它。
+ * ` 或者换句话说,将其转换为规范路径。
+ * ` 在UNIX样式的文件系统中,为period。
+ * ` 指当前目录。此外,双倍..将目录上移
+ * ` 请注意,返回的规范路径必须始终以斜杠/开头。
+ * ` 并且两个目录名称之间只能有一个斜杠/。
+ * ` 最后的目录名称(如果存在)不得以/结尾。
+ * ` 同样,规范路径必须是代表绝对路径的最短字符串。
+ * `
+ * ` Example 1:
+ * ` Input: "/home/"
+ * ` Output: "/home"
+ * ` Explanation:
+ * ` Note that there is no trailing slash after the last directory name.
+ * ` Example 2:
+ * ` Input: "/../"
+ * ` Output: "/"
+ * ` Explanation:
+ * ` Going one level up from the root directory is a no-op,
+ * ` as the root level is the highest level you can go.
+ * ` Example 3:
+ * ` Input: "/home//foo/"
+ * ` Output: "/home/foo"
+ * ` Explanation:
+ * ` In the canonical path, multiple consecutive slashes are replaced by a single one.
+ * ` Example 4:
+ * ` Input: "/a/./b/../../c/"
+ * ` Output: "/c"
+ * ` Example 5:
+ * ` Input: "/a/../../b/../c//.//"
+ * ` Output: "/c"
+ * ` Example 6:
+ * ` Input: "/a//b////c/d//././/.."
+ * ` Output: "/a/b/c"
+ * @Version: 1.0
+ */
+public class _71_simplify_path {
+ public static void main(String[] args) {
+ System.out.println(simplifyPath("/a//b////c/d//././/.."));
+ }
+
+ public static String simplifyPath(String path) {
+ if (path == null || "".equals(path)) {
+ return "";
+ }
+ Stack stack = new Stack<>();
+ String[] split = path.split("/");
+ HashSet pathSet = new HashSet<>(Arrays.asList("..", ".", ""));
+ for (String s : split) {
+ if ("..".equals(s) && !stack.isEmpty()) {
+ stack.pop();
+ } else if (!pathSet.contains(s)) {
+ stack.push(s);
+ }
+ }
+
+ if (stack.isEmpty()) {
+ return "/";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (String s : stack) {
+ sb.append("/").append(s);
+ }
+ return sb.toString();
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_91_decode_ways.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_91_decode_ways.java
new file mode 100644
index 0000000..fd36509
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_91_decode_ways.java
@@ -0,0 +1,55 @@
+package com.leosanqing.leetcode.medium.string;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/22 下午4:16
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * ` A message containing letters from A-Z is being encoded to numbers using the following mapping:
+ * ` 'A' -> 1 'B' -> 2 ... 'Z' -> 26
+ * ` Given a non-empty string containing only digits, determine the total number of ways to decode it.
+ * ` Example 1:
+ * ` Input: "12"
+ * ` Output: 2
+ * ` Explanation:
+ * ` It could be decoded as "AB" (1 2) or "L" (12).
+ * ` Example 2:
+ * ` Input: "226"
+ * ` Output: 3
+ * ` Explanation:
+ * ` It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
+ * @Version: 1.0
+ */
+public class _91_decode_ways {
+ public static void main(String[] args) {
+
+ System.out.println(numDecodings("2262"));
+ }
+
+ public static int numDecodings(String s) {
+ int[] dp = new int[s.length() + 1];
+ dp[0] = 1;
+ dp[1] = s.charAt(0) != '0' ? 1 : 0;
+
+ for (int i = 2; i <= s.length(); i++) {
+ int first = Integer.parseInt(s.substring(i - 1, i));
+ int second = Integer.parseInt(s.substring(i - 2, i));
+
+
+ // 如果这位数是 1-9, 那么 他可以就等于之前的位数,按照单个算
+ // 如 2221 我如果只看最后一位1,那么他的可能性肯定只会等于 222的可能性
+ if (first >= 1 && first <= 9) {
+ dp[i] = dp[i - 1];
+ }
+
+ // 如果 我们 两位 两位看,他的可能性就是之前一位的加上 两位的可能性
+ // 如 1211 最后 1 的可能性就是 121 + 12 的可能性
+ if (second >= 10 && second <= 26) {
+ dp[i] += dp[i - 2];
+ }
+ }
+ return dp[s.length()];
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_93_restore_IP_addresses.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_93_restore_IP_addresses.java
new file mode 100644
index 0000000..d4eae09
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_93_restore_IP_addresses.java
@@ -0,0 +1,90 @@
+package com.leosanqing.leetcode.medium.string;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/23 下午4:47
+ * @Package: com.leosanqing.leetcode.medium.string
+ * @Description: 1
+ * ` Given a string containing only digits, restore it by returning all possible valid IP address combinations.
+ * ` A valid IP address consists of exactly four integers (each integer is between 0 and 255) separated by
+ * single points.
+ * ` Example:
+ * ` Input: "25525511135"
+ * ` Output: ["255.255.11.135", "255.255.111.35"]
+ * @Version: 1.0
+ */
+public class _93_restore_IP_addresses {
+
+ public static void main(String[] args) {
+ String s = "25525511135";
+ restoreIpAddresses(s);
+
+ System.out.println(s.substring(0,1));
+ }
+
+ public static List restoreIpAddresses(String s) {
+ if (s.length() < 4 || s.length() > 12) {
+ return new ArrayList<>();
+ }
+
+ List result = new ArrayList<>();
+ doRestore(result, "", s, 0);
+ return result;
+ }
+
+ public static List restoreIpAddresses1(String s) {
+ if (s.length() < 4 || s.length() > 12) {
+ return new ArrayList<>();
+ }
+ List result = new ArrayList<>();
+ for (int a = 1; a <= 3; a++) {
+ for (int b = 1; b <= 3; b++) {
+ for (int c = 1; c <= 3; c++) {
+ for (int d = 1; d <= 3; d++) {
+ if (a + b + c + d == s.length()) {
+ int num1 = Integer.parseInt(s.substring(0, a));
+ int num2 = Integer.parseInt(s.substring(a, a + b));
+ int num3 = Integer.parseInt(s.substring(a + b, a + b + c));
+ int num4 = Integer.parseInt(s.substring(a + b + c));
+
+ if (num1 <= 255 && num2 <= 255 && num3 <= 255 && num4 <= 255) {
+ result.add(num1 + "." + num2 + "." + num3 + "." + num4);
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ *
+ * @param result
+ * @param path 已经组成的ip地址
+ * @param s 去掉path 后的 剩余的字符 如初始为 2222,path 为 2.2 str 为22
+ * @param k 已经有几段ip地址了 如 运行到 k=2 ,这个时候 path 为 22.22
+ */
+ private static void doRestore(List result, String path, String s, int k) {
+ if (k == 4 || s.isEmpty()) {
+ if (k == 4 && s.isEmpty()) {
+ result.add(path.substring(1));
+ }
+ return;
+ }
+
+ // 如果 s开头为0,只能截取1个字符,不然会出现 22.02 不符合规则
+ for (int i = 1; i <= (s.charAt(0) == '0' ? 1 : 3) && i <= s.length(); i++) {
+ //
+ String part = s.substring(0, i);
+ // 必须小于 255
+ if (Integer.parseInt(part) <= 255) {
+ doRestore(result, path + "." + part, s.substring(i), k + 1);
+ }
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java
new file mode 100644
index 0000000..c0ad5f0
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java
@@ -0,0 +1,131 @@
+package com.leosanqing.leetcode.medium.struct;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
+ * 实现 LRUCache 类:
+ *
+ * LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
+ * int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
+ * void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
+ *
+ * 进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?
+ *
+ * 示例:
+ *
+ * 输入
+ * ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
+ * [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
+ * 输出
+ * [null, null, null, 1, null, -1, null, -1, 3, 4]
+ *
+ * 解释
+ * LRUCache lRUCache = new LRUCache(2);
+ * lRUCache.put(1, 1); // 缓存是 {1=1}
+ * lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
+ * lRUCache.get(1); // 返回 1
+ * lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
+ * lRUCache.get(2); // 返回 -1 (未找到)
+ * lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
+ * lRUCache.get(1); // 返回 -1 (未找到)
+ * lRUCache.get(3); // 返回 3
+ * lRUCache.get(4); // 返回 4
+ * @author: rtliu
+ * @date: 2021/4/25 9:57 上午
+ */
+public class _146_LRU_Cache {
+ public static void main(String[] args) {
+ LRUCache lruCache = new LRUCache(1);
+ lruCache.put(2,1);
+ System.out.println(lruCache.get(2));
+ }
+
+ static class DLinkedNode {
+ int value;
+ int key;
+ DLinkedNode pre;
+ DLinkedNode next;
+
+ public DLinkedNode() {
+ }
+
+ public DLinkedNode(int key, int value) {
+ this.value = value;
+ this.key = key;
+ }
+ }
+
+ static class LRUCache {
+ private Map map = new HashMap<>();
+ private int size;
+ private int capacity;
+ private DLinkedNode head;
+ private DLinkedNode tail;
+
+ public LRUCache(int capacity) {
+ this.size = 0;
+ this.capacity = capacity;
+
+ // 使用虚拟的头尾节点,防止出现极限问题
+ head = new DLinkedNode();
+ tail = new DLinkedNode();
+ head.next = tail;
+ tail.pre = head;
+ }
+
+ public int get(int key) {
+ DLinkedNode node = map.get(key);
+ if (node == null) {
+ return -1;
+ }
+ moveToHead(node);
+ return node.value;
+ }
+
+ public void put(int key, int value) {
+ DLinkedNode node = map.get(key);
+ if (node == null) {
+ DLinkedNode dLinkedNode = new DLinkedNode(key, value);
+ map.put(key, dLinkedNode);
+
+ // 设置 头节点
+ addToHead(dLinkedNode);
+
+ ++size;
+ if (size > capacity) {
+ map.remove(removeTail().key);
+ --size;
+ }
+ } else {
+ node.value = value;
+ moveToHead(node);
+ }
+ }
+
+ private DLinkedNode removeTail() {
+ DLinkedNode pre = tail.pre;
+ removeNode(pre);
+ return pre;
+ }
+
+ private void removeNode(DLinkedNode node) {
+ node.pre.next = node.next;
+ node.next.pre = node.pre;
+ }
+
+ private void addToHead(DLinkedNode dLinkedNode) {
+ dLinkedNode.pre = head;
+ dLinkedNode.next = head.next;
+
+ head.next.pre = dLinkedNode;
+ head.next = dLinkedNode;
+ }
+
+ private void moveToHead(DLinkedNode dLinkedNode) {
+ removeNode(dLinkedNode);
+ addToHead(dLinkedNode);
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/Node.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/Node.java
new file mode 100644
index 0000000..417f73d
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/Node.java
@@ -0,0 +1,21 @@
+package com.leosanqing.leetcode.medium.tree;
+
+public class Node {
+ public int val;
+ public Node left;
+ public Node right;
+ public Node next;
+
+ public Node() {}
+
+ public Node(int _val) {
+ val = _val;
+ }
+
+ public Node(int _val, Node _left, Node _right, Node _next) {
+ val = _val;
+ left = _left;
+ right = _right;
+ next = _next;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/TreeNode.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/TreeNode.java
new file mode 100644
index 0000000..ad4431f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/TreeNode.java
@@ -0,0 +1,17 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @author zhuerchong
+ */
+public class TreeNode {
+ public int val;
+ public TreeNode left;
+ public TreeNode right;
+ public TreeNode() {}
+ public TreeNode(int val) { this.val = val; }
+ public TreeNode(int val, TreeNode left, TreeNode right) {
+ this.val = val;
+ this.left = left;
+ this.right = right;
+ }
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java
new file mode 100644
index 0000000..a11fa00
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java
@@ -0,0 +1,65 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/27 下午4:07
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a binary tree, return the level order traversal of its nodes' values.
+ * ` (ie, from left to right, level by level).
+ * ` For example: Given binary tree [3,9,20,null,null,15,7],
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` return its level order traversal as:
+ * ` [
+ * ` [3],
+ * ` [9,20],
+ * ` [15,7]
+ * ` ]
+ * @Version: 1.0
+ */
+public class _102_binary_tree_level_order_traversal {
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(3);
+ treeNode.left = new TreeNode(9);
+ treeNode.right = new TreeNode(20);
+ treeNode.right.left = new TreeNode(1);
+ treeNode.right.right = new TreeNode(7);
+
+ System.out.println(JSON.toJSONString(levelOrder(treeNode)));
+ }
+
+ public static List> levelOrder(TreeNode root) {
+ List> answer = new ArrayList<>();
+
+ backtrace(answer, 0, root);
+ return answer;
+ }
+
+ private static void backtrace(List> answer, int depth, TreeNode node) {
+ if (node == null) {
+ return;
+ }
+
+ if (depth >= answer.size()) {
+ List list = new ArrayList<>();
+ list.add(node.val);
+ answer.add(list);
+ } else {
+ answer.get(depth).add(node.val);
+ }
+
+ backtrace(answer, depth + 1, node.left);
+ backtrace(answer, depth + 1, node.right);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_103_binary_tree_zigzag_level_order_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_103_binary_tree_zigzag_level_order_traversal.java
new file mode 100644
index 0000000..2b4075a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_103_binary_tree_zigzag_level_order_traversal.java
@@ -0,0 +1,93 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/27 下午5:29
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a binary tree, return the zigzag level order traversal of its nodes' values.
+ * ` (ie, from left to right, then right to left for the next level and alternate between).
+ * ` 给定一棵二叉树,返回其节点值的之字形级别顺序遍历。
+ * ` (即,从左到右,然后从右到左进入下一个级别,并在之间切换)。
+ * ` For example:
+ * ` Given binary tree [3,9,20,null,null,15,7],
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * ` return its zigzag level order traversal as:
+ * ` [
+ * ` [3],
+ * ` [20,9],
+ * ` [15,7]
+ * ` ]
+ * @Version: 1.0
+ */
+public class _103_binary_tree_zigzag_level_order_traversal {
+ public List> zigzagLevelOrder(TreeNode root) {
+ if (root == null) {
+ return new ArrayList<>();
+ }
+ List> answer = new ArrayList<>();
+ answer.add(Arrays.asList(root));
+
+ List> res = new ArrayList<>();
+ res.add(Arrays.asList(root.val));
+ findAnswer(answer, new ArrayList<>(), res, new ArrayList<>());
+ return res;
+ }
+
+ /**
+ * 这个就简单的改造一下 102的解法,加一个条件判断
+ * @param lists
+ * @param list
+ * @param answer
+ * @param temp
+ */
+ private static void findAnswer(List> lists, List list, List> answer,
+ List temp) {
+ boolean flag = true;
+ while (true) {
+ List treeNodes = lists.get(lists.size() - 1);
+ for (int i = treeNodes.size() - 1; i >= 0; i--) {
+ if (flag) {
+ if (treeNodes.get(i).right != null) {
+ list.add(treeNodes.get(i).right);
+ temp.add(treeNodes.get(i).right.val);
+ }
+ if (treeNodes.get(i).left != null) {
+ list.add(treeNodes.get(i).left);
+ temp.add(treeNodes.get(i).left.val);
+ }
+ } else {
+ if (treeNodes.get(i).left != null) {
+ list.add(treeNodes.get(i).left);
+ temp.add(treeNodes.get(i).left.val);
+ }
+
+ if (treeNodes.get(i).right != null) {
+ list.add(treeNodes.get(i).right);
+ temp.add(treeNodes.get(i).right.val);
+ }
+ }
+
+ }
+
+
+ if (list.isEmpty()) {
+ return;
+ }
+ lists.add(new ArrayList<>(list));
+ answer.add(new ArrayList<>(temp));
+ list.clear();
+ temp.clear();
+
+ flag = !flag;
+ }
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java
new file mode 100644
index 0000000..c2dd3ea
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java
@@ -0,0 +1,74 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/28 下午7:29
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given preorder and inorder traversal of a tree, construct the binary tree.
+ * ` Note: You may assume that duplicates do not exist in the tree.
+ * ` For example, given preorder = [3,9,20,15,7] inorder = [9,3,15,20,7]
+ * ` Return the following binary tree:
+ * `
+ * ` 给定一棵树的前序和有序遍历,构造二叉树。
+ * ` 注意:您可以假定树中不存在重复项。
+ * ` 例如,给定的先序遍历 = [3,9,20,15,7] 中序遍历 = [9,3,15,20,7]
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * @Version: 1.0
+ */
+public class _105_construct_binary_tree_from_preorder_and_inorder_traversal {
+
+ public static void main(String[] args) {
+ int[] preorder = {3, 9, 2, 11, 14, 8, 20, 15, 16, 7, 22};
+ int[] inorder = {11, 2, 14, 9, 8, 3, 16, 15, 20, 22, 7};
+
+
+// TreeNode treeNode1 = backTrace(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
+
+
+ TreeNode treeNode = buildTree(preorder, inorder);
+
+
+ }
+
+ private static Map indexMap;
+
+ public static TreeNode buildTree(int[] preorder, int[] inorder) {
+
+ // 构造哈希映射,帮助我们快速定位根节点
+ indexMap = new HashMap<>(preorder.length * 2);
+ for (int i = 0; i < preorder.length; i++) {
+ indexMap.put(inorder[i], i);
+ }
+ return backtrace(preorder, 0, preorder.length - 1, inorder, 0, preorder.length - 1);
+ }
+
+ private static TreeNode backtrace(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd) {
+ if (preStart > preEnd) {
+ return null;
+ }
+
+ // 在中序遍历中定位根节点
+ int inorderRoot = indexMap.get(preorder[preStart]);
+
+ // 先把根节点建立出来
+ TreeNode root = new TreeNode(preorder[preStart]);
+ // 得到左子树中的节点数目
+ int sizeLeftSubtree = inorderRoot - inStart;
+ // 递归地构造左子树,并连接到根节点
+ // 先序遍历中「从 左边界+1 开始的 sizeLeftSubtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
+ root.left = backtrace(preorder, preStart + 1, preStart + sizeLeftSubtree, inorder, inStart, inorderRoot - 1);
+ // 递归地构造右子树,并连接到根节点
+ // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
+ root.right = backtrace(preorder, preStart + sizeLeftSubtree + 1, preEnd, inorder, inorderRoot + 1, inEnd);
+
+ return root;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_106_construct_binary_tree_from_inorder_and_postorder_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_106_construct_binary_tree_from_inorder_and_postorder_traversal.java
new file mode 100644
index 0000000..74dac3c
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_106_construct_binary_tree_from_inorder_and_postorder_traversal.java
@@ -0,0 +1,61 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/29 上午10:43
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given inorder and postorder traversal of a tree, construct the binary tree.
+ * ` Note: You may assume that duplicates do not exist in the tree.
+ * ` For example,
+ * ` given inorder = [9,3,15,20,7] postorder = [9,15,7,20,3]
+ * ` Return the following binary tree:
+ * ` 3
+ * ` / \
+ * ` 9 20
+ * ` / \
+ * ` 15 7
+ * @Version: 1.0
+ */
+public class _106_construct_binary_tree_from_inorder_and_postorder_traversal {
+
+ public static void main(String[] args) {
+
+
+ }
+
+ public TreeNode buildTree(int[] inorder, int[] postorder) {
+
+ return backTrace(inorder, 0, inorder.length - 1, postorder, postorder.length - 1);
+ }
+
+ /**
+ * 这个跟 之前 105题解法思路一样,只不过顺序不一样
+ *
+ * @param inorder
+ * @param inStart
+ * @param inEnd
+ * @param postorder
+ * @param postEnd
+ * @return
+ */
+ private static TreeNode backTrace(int[] inorder, int inStart, int inEnd, int[] postorder, int postEnd) {
+
+ if (postEnd < 0 || inStart > inEnd) {
+ return null;
+ }
+
+ TreeNode root = new TreeNode(postorder[postEnd]);
+
+ int inIndex = 0;
+ for (int i = inEnd; i >= inStart; i--) {
+ if (root.val == inorder[i]) {
+ inIndex = i;
+ }
+ }
+
+ root.right = backTrace(inorder, inIndex + 1, inEnd, postorder, postEnd - 1);
+ root.left = backTrace(inorder, inStart, inIndex - 1, postorder, postEnd + inIndex - inEnd - 1);
+ return root;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_109_convert_sorted_list_to_binary_search_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_109_convert_sorted_list_to_binary_search_tree.java
new file mode 100644
index 0000000..8e3ff06
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_109_convert_sorted_list_to_binary_search_tree.java
@@ -0,0 +1,50 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import com.leosanqing.leetcode.medium.list.ListNode;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/30 上午9:56
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a singly linked list where elements are sorted in ascending order, convert it to a height
+ * balanced BST.
+ * ` For this problem,
+ * ` a height-balanced binary tree is defined as a binary tree in which
+ * ` the depth of the two subtrees of every node never differ by more than 1.
+ * ` Example:
+ * ` Given the sorted linked list: [-10,-3,0,5,9],
+ * ` One possible answer is: [0,-3,9,-10,null,5],
+ * ` which represents the following height balanced BST:
+ * ` 0
+ * ` / \
+ * ` -3 9
+ * ` / /
+ * ` -10 5
+ * @Version: 1.0
+ */
+public class _109_convert_sorted_list_to_binary_search_tree {
+
+
+ public TreeNode sortedListToBST(ListNode head) {
+ return backTrace(head, null);
+ }
+
+ private static TreeNode backTrace(ListNode head, ListNode tail) {
+ ListNode slow = head;
+ ListNode fast = head;
+ if (head == tail) {
+ return null;
+ }
+
+ while (fast != tail && fast.next != tail) {
+ fast = fast.next.next;
+ slow = slow.next;
+ }
+
+ TreeNode root = new TreeNode(slow.val);
+ root.left = backTrace(head, slow);
+ root.right = backTrace(slow.next, tail);
+ return root;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_112_path_sum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_112_path_sum.java
new file mode 100644
index 0000000..5d432ac
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_112_path_sum.java
@@ -0,0 +1,54 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/30 下午5:24
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * Given a binary tree and a sum,
+ * determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
+ * Note: A leaf is a node with no children.
+ * Example:
+ * Given the below binary tree and sum = 22,
+ * 5
+ * / \
+ * 4 8
+ * / / \
+ * 11 13 4
+ * / \ \
+ * 7 2 1 return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
+ * @Version: 1.0
+ */
+public class _112_path_sum {
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(5);
+ treeNode.left = new TreeNode(4);
+ treeNode.right = new TreeNode(8);
+ treeNode.left.left = new TreeNode(11);
+ treeNode.right.left = new TreeNode(13);
+ treeNode.right.right = new TreeNode(4);
+ treeNode.left.left.left = new TreeNode(7);
+ treeNode.left.left.right = new TreeNode(2);
+ treeNode.right.right.right = new TreeNode(1);
+
+ System.out.println(hasPathSum(treeNode, 22));
+ }
+
+ public static boolean hasPathSum(TreeNode root, int sum) {
+
+
+ return backTrace(root, sum);
+ }
+
+ private static boolean backTrace(TreeNode root, int sum) {
+ if (root == null) {
+ return false;
+ }
+ if (root.left == null && root.right == null && root.val == sum) {
+ return true;
+ }
+
+ return backTrace(root.left, sum-root.val) || backTrace(root.right, sum-root.val);
+
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_113_path_sumII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_113_path_sumII.java
new file mode 100644
index 0000000..91f7c34
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_113_path_sumII.java
@@ -0,0 +1,64 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 上午11:26
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * Given a binary tree and a sum,
+ * find all root-to-leaf paths where each path's sum equals the given sum.
+ * Note: A leaf is a node with no children.
+ * Example:
+ * Given the below binary tree and sum = 22,
+ * 5
+ * / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1 Return: [ [5,4,11,2], [5,8,4,5] ]
+ * @Version: 1.0
+ */
+public class _113_path_sumII {
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(5);
+ treeNode.left = new TreeNode(4);
+ treeNode.right = new TreeNode(8);
+ treeNode.left.left = new TreeNode(11);
+ treeNode.right.left = new TreeNode(13);
+ treeNode.right.right = new TreeNode(4);
+ treeNode.left.left.left = new TreeNode(7);
+ treeNode.left.left.right = new TreeNode(2);
+ treeNode.right.right.right = new TreeNode(1);
+ treeNode.right.right.left = new TreeNode(5);
+
+ pathSum(treeNode, 22);
+ }
+
+ public static List> pathSum(TreeNode root, int sum) {
+
+ if (root == null) {
+ return new ArrayList<>();
+ }
+
+ List> answer = new ArrayList<>();
+ backTrace(answer, new ArrayList<>(), root, sum);
+ return answer;
+ }
+
+ private static void backTrace(List> answer, List list, TreeNode root, int sum) {
+ if (root == null) {
+ return;
+ }
+ list.add(root.val);
+
+ if (root.left == null && root.right == null && sum == root.val) {
+ answer.add(new ArrayList<>(list));
+ list.remove(list.size() - 1);
+ return;
+ }
+
+ backTrace(answer, list, root.left, sum - root.val);
+ backTrace(answer, list, root.right, sum - root.val);
+ list.remove(list.size() - 1);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java
new file mode 100644
index 0000000..3a72eab
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java
@@ -0,0 +1,55 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 下午2:03
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a binary tree, flatten it to a linked list in-place.
+ * ` For example, given the following tree:
+ * ` 1
+ * ` / \
+ * ` 2 5
+ * ` / \ \
+ * ` 3 4 6
+ * ` The flattened tree should look like:
+ * ` 1
+ * ` \
+ * ` 2
+ * ` \
+ * ` 3
+ * ` \
+ * ` 4
+ * ` \
+ * ` 5
+ * ` \
+ * ` 6
+ * @Version: 1.0
+ */
+public class _114_flatten_binary_tree_to_linked_list {
+
+ public void flatten(TreeNode root) {
+ if (root == null) {
+ return;
+ }
+
+ TreeNode left = root.left;
+ TreeNode right = root.right;
+
+ right.left = null;
+
+ flatten(left);
+ flatten(right);
+
+ root.right = left;
+
+ // 找到 左子树 最后一个节点,将其连接上
+ TreeNode cur = root;
+ while (cur.right != null) {
+ cur = cur.right;
+ }
+ cur.right = right;
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_116_populating_next_right_pointers_in_each_node.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_116_populating_next_right_pointers_in_each_node.java
new file mode 100644
index 0000000..c1ff4e8
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_116_populating_next_right_pointers_in_each_node.java
@@ -0,0 +1,64 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Stack;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 下午2:50
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` https://leetcode.com/problems/populating-next-right-pointers-in-each-node/
+ * @Version: 1.0
+ */
+public class _116_populating_next_right_pointers_in_each_node {
+
+ public static void main(String[] args) {
+ Node treeNode = new Node(1);
+ treeNode.left = new Node(2);
+ treeNode.right = new Node(3);
+ treeNode.left.left = new Node(4);
+ treeNode.left.right = new Node(5);
+ treeNode.right.left = new Node(6);
+ treeNode.right.right = new Node(7);
+
+ connect(treeNode);
+ }
+
+ public static Node connect(Node root) {
+
+ if (root == null) {
+ return null;
+ }
+ Queue queue = new LinkedList<>();
+ queue.offer(root);
+ while (!queue.isEmpty()) {
+
+ int queueSize = queue.size() - 1;
+ Node node = queue.poll();
+
+ // because of perfect binary tree
+ if (node == null) {
+ break;
+ }
+
+ for (int i = 0; i <= queueSize; i++) {
+ queue.offer(node.left);
+ queue.offer(node.right);
+
+ if (i == queueSize) {
+ node.next = null;
+ break;
+ }
+
+ Node temp = queue.poll();
+ node.next = temp;
+ node = temp;
+ }
+ }
+ return root;
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_117_populating_next_right_pointers_in_each_nodeII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_117_populating_next_right_pointers_in_each_nodeII.java
new file mode 100644
index 0000000..325a64a
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_117_populating_next_right_pointers_in_each_nodeII.java
@@ -0,0 +1,52 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/31 下午3:59
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/
+ * @Version: 1.0
+ */
+public class _117_populating_next_right_pointers_in_each_nodeII {
+ public static Node connect(Node root) {
+
+ if (root == null) {
+ return null;
+ }
+ Queue queue = new LinkedList<>();
+ queue.offer(root);
+ while (!queue.isEmpty()) {
+
+ int queueSize = queue.size() - 1;
+ Node node = queue.poll();
+
+ // because of perfect binary tree
+ if (node == null) {
+ break;
+ }
+
+ for (int i = 0; i <= queueSize; i++) {
+ if (node.left != null) {
+ queue.offer(node.left);
+ }
+ if (node.right != null) {
+ queue.offer(node.right);
+ }
+
+ if (i == queueSize) {
+ node.next = null;
+ break;
+ }
+
+ Node temp = queue.poll();
+ node.next = temp;
+ node = temp;
+ }
+ }
+ return root;
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_129_sum_root_to_leaf_numbers.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_129_sum_root_to_leaf_numbers.java
new file mode 100644
index 0000000..8df008e
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_129_sum_root_to_leaf_numbers.java
@@ -0,0 +1,77 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/8/3 上午11:26
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a binary tree containing digits from 0-9 only,
+ * ` each root-to-leaf path could represent a number.
+ * ` An example is the root-to-leaf path 1->2->3 which represents the number 123.
+ * ` Find the total sum of all root-to-leaf numbers.
+ * ` Note: A leaf is a node with no children.
+ * ` Example:
+ * ` Input: [1,2,3]
+ * ` 1
+ * ` / \
+ * ` 2 3
+ * ` Output: 25
+ * ` Explanation:
+ * ` The root-to-leaf path 1->2 represents the number 12.
+ * ` The root-to-leaf path 1->3 represents the number 13.
+ * ` Therefore, sum = 12 + 13 = 25.
+ * ` Example 2:
+ * ` Input: [4,9,0,5,1]
+ * ` 4
+ * ` / \
+ * ` 9 0
+ * ` / \
+ * ` 5 1
+ * ` Output: 1026
+ * ` Explanation:
+ * ` The root-to-leaf path 4->9->5 represents the number 495.
+ * ` The root-to-leaf path 4->9->1 represents the number 491.
+ * ` The root-to-leaf path 4->0 represents the number 40. Therefore, sum = 495 + 491 + 40 = 1026.
+ * @Version: 1.0
+ */
+public class _129_sum_root_to_leaf_numbers {
+
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(1);
+ treeNode.right = new TreeNode(3);
+ treeNode.left = new TreeNode(2);
+ treeNode.left.left = new TreeNode(4);
+ treeNode.left.right = new TreeNode(5);
+
+ sumNumbers(treeNode);
+ }
+
+ public static int sumNumbers(TreeNode root) {
+ List list = new ArrayList<>();
+ backTrace(root, 0, list);
+ int sum = 0;
+ for (Integer integer : list) {
+ sum += integer;
+ }
+ return sum;
+ }
+
+
+ private static void backTrace(TreeNode root, int val, List list) {
+ if(root == null){
+ return;
+ }
+ val = val * 10 +root.val;
+
+ if(root.left == null && root.right == null){
+
+ list.add(val);
+ return;
+ }
+ backTrace(root.left, val, list);
+ backTrace(root.right, val, list);
+ }
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_208_implementTrie.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_208_implementTrie.java
new file mode 100644
index 0000000..f5dd11f
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_208_implementTrie.java
@@ -0,0 +1,162 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/17 上午10:33
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 实现 一个 Trie
+ * Implement a trie with insert, search, and startsWith methods.
+ *
+ * Example:
+ *
+ * Trie trie = new Trie();
+ *
+ * trie.insert("apple");
+ * trie.search("apple"); // returns true
+ * trie.search("app"); // returns false
+ * trie.startsWith("app"); // returns true
+ * trie.insert("app");
+ * trie.search("app"); // returns true
+ *
+ *
+ * 很多人可能不了解 Trie
+ * 在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。
+ * 与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。
+ * 一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。
+ * 一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
+ * @Version: 1.0
+ */
+public class _208_implementTrie {
+
+ public static void main(String[] args) {
+ Trie trie = new Trie();
+ trie.insert("apple");
+ boolean apple = trie.search("apple");
+ System.out.println(apple);
+ }
+}
+
+class TrieNode{
+ private final Map children = new HashMap<>();
+
+ public boolean isEnd = false;
+
+ public void putChildIfAbsent(char c){
+ // 直接调用 HashMap 的代码,创建 子节点
+ children.putIfAbsent(c,new TrieNode());
+ }
+
+ public TrieNode getChildren(char c){
+ return children.get(c);
+ }
+}
+
+class Trie {
+
+
+ TrieNode root = new TrieNode();
+
+ /** Initialize your data structure here. */
+ public Trie() {
+
+ }
+
+ /** Inserts a word into the trie. */
+ public void insert(String word) {
+ TrieNode curr = root;
+ for (char ch : word.toCharArray()) {
+ curr.putChildIfAbsent(ch);
+ curr = curr.getChildren(ch);
+ }
+ curr.isEnd = true;
+ }
+
+ /** Returns if the word is in the trie. */
+ public boolean search(String word) {
+ TrieNode curr = root;
+ for (char ch : word.toCharArray()) {
+ curr = curr.getChildren(ch);
+ if (curr == null) {
+ return false;
+ }
+ }
+ return curr.isEnd;
+ }
+
+ /** Returns if there is any word in the trie that starts with the given prefix. */
+ public boolean startsWith(String prefix) {
+ TrieNode curr = root;
+ for (char c : prefix.toCharArray()) {
+ curr = curr.getChildren(c);
+ if (curr == null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+
+/**
+ * 使用 数组实现
+ */
+class Trie2 {
+
+
+ TrieNode2 root = new TrieNode2();
+
+ /** Initialize your data structure here. */
+ public Trie2() {
+
+ }
+
+ /** Inserts a word into the trie. */
+ public void insert(String word) {
+ TrieNode2 curr = root;
+ for (char ch : word.toCharArray()) {
+ if(curr.children[ch - 'a'] != null){
+ curr = curr.children[ch - 'a'];
+ }else{
+ curr.children[ch - 'a'] = new TrieNode2();
+ }
+ }
+ curr.isEnd = true;
+ }
+
+ /** Returns if the word is in the trie. */
+ public boolean search(String word) {
+ TrieNode2 curr = root;
+ for (char ch : word.toCharArray()) {
+ curr = curr.children[ch - 'a'];
+ if (curr == null) {
+ return false;
+ }
+ }
+ return curr.isEnd;
+ }
+
+ /** Returns if there is any word in the trie that starts with the given prefix. */
+ public boolean startsWith(String prefix) {
+ TrieNode2 curr = root;
+ for (char c : prefix.toCharArray()) {
+ curr = curr.children[c - 'a'];
+ if (curr == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+class TrieNode2{
+ /** 因为有26个字符 */
+ public TrieNode2[] children = new TrieNode2[26];
+
+ public boolean isEnd = false;
+
+
+}
\ No newline at end of file
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_211_addAndSearchWord_dataStructureDesign.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_211_addAndSearchWord_dataStructureDesign.java
new file mode 100644
index 0000000..45fc7ac
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_211_addAndSearchWord_dataStructureDesign.java
@@ -0,0 +1,83 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/28 下午3:58
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: Design a data structure that supports the following two operations:
+ * void addWord(word) bool search(word) search(word) can search a literal word
+ * or a regular expression string containing only letters a-z or .. A . means it can represent any one letter.
+ * Example:
+ * addWord("bad")
+ * addWord("dad")
+ * addWord("mad")
+ * search("pad") -> false
+ * search("bad") -> true
+ * search(".ad") -> true
+ * search("b..") -> true
+ * @Version: 1.0
+ */
+public class _211_addAndSearchWord_dataStructureDesign {
+
+}
+
+class WordDictionary {
+ TrieNode1 root = new TrieNode1();
+
+ /** Initialize your data structure here. */
+ public WordDictionary() {
+
+ }
+
+ /** Adds a word into the data structure. */
+ public void addWord(String word) {
+ TrieNode1 curr = root;
+ if(word != null && word.length() > 0){
+
+ for (char c : word.toCharArray()) {
+ if (curr.children[c - 'a'] == null) {
+ curr.children[c - 'a'] = new TrieNode1();
+ }
+ curr = curr.children[c -'a'];
+
+ }
+ curr.isEnd = true;
+
+ }
+ }
+
+ /** Returns if the word is in the data structure.
+ * A word could contain the dot character '.' to represent any one letter. */
+ public boolean search(String word) {
+ return helper(word, 0 , root);
+ }
+
+
+ private boolean helper(String word, int index, TrieNode1 curr){
+ if(index >= word.length()){
+ return curr.isEnd;
+ }
+ char c = word.charAt(index);
+
+ if('.' == c){
+ for (int i = 0; i < curr.children.length; i++) {
+ // 当出现 . 的时候,递归遍历
+ if(curr.children[i] != null && helper(word, index+1, curr.children[i])){
+ return true;
+ }
+ }
+ return false;
+ }else {
+ return (curr.children[c - 'a'] != null) && helper(word,index +1, curr.children[c - 'a']);
+ }
+ }
+}
+
+class TrieNode1 {
+ TrieNode1[] children = new TrieNode1[26];
+
+ boolean isEnd = false;
+
+}
+
+
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_257_binaryTreePaths.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_257_binaryTreePaths.java
new file mode 100644
index 0000000..15f7951
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_257_binaryTreePaths.java
@@ -0,0 +1,57 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/22 下午3:08
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: Given a binary tree, return all root-to-leaf paths.
+ * @Version: 1.0
+ *
+ *
+ *
+ * Example:
+ *
+ * Input:
+ *
+ * 1
+ * / \
+ * 2 3
+ * \
+ * 5
+ *
+ * Output: ["1->2->5", "1->3"]
+ *
+ * Explanation: All root-to-leaf paths are: 1->2->5, 1->3
+ */
+public class _257_binaryTreePaths {
+
+ public List binaryTreePaths(TreeNode root) {
+ List strings = new ArrayList<>();
+
+ if (root != null) {
+ searchBT(root,"",strings);
+ }
+
+
+ return strings;
+ }
+
+ private void searchBT(TreeNode node, String path, List list) {
+ if (node.left == null && node.right == null) {
+ list.add(path + node.val);
+
+ }
+ if (node.right != null) {
+ searchBT(node.right, path + node.val + "->", list);
+ }
+ if(node.left != null){
+ searchBT(node.left, path + node.val + "->", list);
+ }
+ }
+
+}
+
+
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_94_binary_tree_inorder_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_94_binary_tree_inorder_traversal.java
new file mode 100644
index 0000000..61ace0b
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_94_binary_tree_inorder_traversal.java
@@ -0,0 +1,61 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/24 上午9:49
+ * @Package: com.leosanqing.leetcode.medium.list
+ * @Description: 1
+ * ` Given a binary tree, return the inorder traversal of its nodes' values.
+ * ` 给定一个二叉树,返回其节点值的有序遍历。
+ * ` Example:
+ * ` Input:
+ * ` [1,null,2,3]
+ * ` 1
+ * ` \
+ * ` 2
+ * ` /
+ * ` 3
+ * ` Output: [1,3,2]
+ * @Version: 1.0
+ */
+public class _94_binary_tree_inorder_traversal {
+
+ // 不使用递归
+ public List inorderTraversal(TreeNode root) {
+ List list = new ArrayList<>();
+
+ Stack stack = new Stack<>();
+ TreeNode cur = root;
+ while (cur != null || !stack.isEmpty()) {
+ while (cur != null) {
+ stack.push(cur);
+ cur = cur.left;
+ }
+
+ cur = stack.pop();
+ list.add(cur.val);
+ cur = cur.right;
+ }
+
+ return list;
+
+ }
+
+
+ // 使用递归
+ private void backTrace(List list, TreeNode node){
+
+ if(node == null){
+ return;
+ }
+ backTrace(list, node.left);
+ list.add(node.val);
+ backTrace(list, node.right);
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_95_unique_binary_search_treesII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_95_unique_binary_search_treesII.java
new file mode 100644
index 0000000..f8f7f63
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_95_unique_binary_search_treesII.java
@@ -0,0 +1,84 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/24 上午10:29
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ..
+ * . n.
+ * ` Example:
+ * ` Input: 3
+ * ` Output:
+ * ` [
+ * ` [1,null,3,2],
+ * ` [3,2,null,1],
+ * ` [3,1,null,null,2],
+ * ` [2,1,3],
+ * ` [1,null,2,null,3]
+ * ` ]
+ * ` Explanation:
+ * ` The above output corresponds to the 5 unique BST's shown below:
+ * ` 1 3 3 2 1
+ * ` \ / / / \ \
+ * ` 3 2 1 1 3 2
+ * ` / / \ \
+ * ` 2 1 2 3
+ * @Version: 1.0
+ */
+public class _95_unique_binary_search_treesII {
+
+ public static void main(String[] args) {
+ generateTrees(8);
+ }
+
+ public static List generateTrees(int n) {
+
+ List[] res = new List[n + 1];
+ res[0] = new ArrayList<>();
+ if (n == 0) {
+ return res[0];
+ }
+ res[0].add(null);
+ res[1] = new ArrayList<>();
+ res[1].add(new TreeNode(1));
+ for (int i = 2; i <= n; i++) {
+ res[i] = new ArrayList<>();
+ for (int j = 1; j <= i; j++) {
+ for (TreeNode nodeL : res[j - 1]) {
+ for (TreeNode nodeR : res[i - j]) {
+ TreeNode node = new TreeNode(j);
+ node.left = nodeL;
+ node.right = clone(nodeR, j);
+ res[i].add(node);
+ }
+ }
+ }
+ }
+ return res[n];
+ }
+
+
+ static TreeNode clone(TreeNode node, int offset) {
+ if (node == null) {
+ return null;
+ }
+ TreeNode newNode = new TreeNode(node.val + offset);
+ newNode.left = clone(node.left, offset);
+ newNode.right = clone(node.right, offset);
+ return newNode;
+ }
+
+
+ private void backTrace(List result, TreeNode cur, TreeNode root, int position, int max) {
+ if (position == max) {
+ result.add(root);
+ }
+
+
+ }
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_96_unique_binary_search_trees.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_96_unique_binary_search_trees.java
new file mode 100644
index 0000000..22351d9
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_96_unique_binary_search_trees.java
@@ -0,0 +1,55 @@
+package com.leosanqing.leetcode.medium.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/24 上午10:29
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ..
+ * . n.
+ * ` Example:
+ * ` Input: 3
+ * ` Output: 5
+ * `
+ * ` Explanation:
+ * ` The above output corresponds to the 5 unique BST's shown below:
+ * ` 1 3 3 2 1
+ * ` \ / / / \ \
+ * ` 3 2 1 1 3 2
+ * ` / / \ \
+ * ` 2 1 2 3
+ * @Version: 1.0
+ */
+public class _96_unique_binary_search_trees {
+
+ public static void main(String[] args) {
+ generateTrees(3);
+ }
+
+
+ /**
+ * 解释 :https://leetcode.com/problems/unique-binary-search-trees/discuss/31666/DP-Solution-in-6-lines-with
+ * -explanation.-F(i-n)-G(i-1)-*-G(n-i)
+ *
+ * @param n
+ * @return
+ */
+ public static int generateTrees(int n) {
+ int[] res = new int[n + 1];
+
+ res[0] = res[1] = 1;
+
+ for (int i = 2; i <= n; i++) {
+ for (int j = 1; j <= i; j++) {
+ res[i] += res[j - 1] * res[i - j];
+ }
+ }
+
+ return res[n];
+ }
+
+
+}
diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java
new file mode 100644
index 0000000..f96d6b5
--- /dev/null
+++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java
@@ -0,0 +1,71 @@
+package com.leosanqing.leetcode.medium.tree;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/7/27 上午10:31
+ * @Package: com.leosanqing.leetcode.medium.tree
+ * @Description: 1
+ * ` Given a binary tree, determine if it is a valid binary search tree (BST).
+ * ` Assume a BST is defined as follows:
+ * ` The left subtree of a node contains only nodes with keys less than the node's key.
+ * ` The right subtree of a node contains only nodes with keys greater than the node's key.
+ * ` Both the left and right subtrees must also be binary search trees.
+ * ` Example 1:
+ * ` 2
+ * ` / \
+ * ` 1 3
+ * ` Input: [2,1,3]
+ * ` Output: true
+ * ` Example 2: 5
+ * ` / \
+ * ` 1 4
+ * ` / \
+ * ` 3 6
+ * ` Input: [5,1,4,null,null,3,6]
+ * ` Output: false
+ * ` Explanation: The root node's value is 5 but its right child's value is 4.
+ * @Version: 1.0
+ */
+public class _98_validate_binary_search_tree {
+ public static void main(String[] args) {
+ TreeNode treeNode = new TreeNode(2);
+ treeNode.left = new TreeNode(1);
+ treeNode.right = new TreeNode(3);
+
+ System.out.println(isValidBST(treeNode));
+ }
+
+ public static boolean isValidBST(TreeNode root) {
+ return backTrace(root, null, null);
+
+ }
+
+ // 又是递归
+ private static boolean backTrace(TreeNode treeNode, Integer min, Integer max) {
+ if (treeNode == null) {
+ return true;
+ }
+
+ // 左子树一定小于父节点,右子树一定大于父节点
+ if ((max != null && treeNode.val >= max)
+ || (min != null && treeNode.val <= min)) {
+ return false;
+ }
+ return backTrace(treeNode.left, min, treeNode.val) && backTrace(treeNode.right, treeNode.val, max);
+ }
+
+ private static boolean backtrace(TreeNode treeNode, Integer max, Integer min) {
+ if (treeNode == null) {
+ return true;
+ }
+
+ if (
+ (max != null && treeNode.val >= max)
+ || (min != null && treeNode.val <= min)
+ ) {
+ return false;
+ }
+ return backtrace(treeNode.left, max, treeNode.val)&&backtrace(treeNode.right, treeNode.val, min);
+ }
+
+}
diff --git a/java-note-algorithm/target/classes/META-INF/java-note-algorithm.kotlin_module b/java-note-algorithm/target/classes/META-INF/java-note-algorithm.kotlin_module
new file mode 100644
index 0000000..a49347a
Binary files /dev/null and b/java-note-algorithm/target/classes/META-INF/java-note-algorithm.kotlin_module differ
diff --git a/knife4j-demo/.idea/$CACHE_FILE$ b/knife4j-demo/.idea/$CACHE_FILE$
new file mode 100644
index 0000000..6cb8985
--- /dev/null
+++ b/knife4j-demo/.idea/$CACHE_FILE$
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/.idea/.gitignore b/knife4j-demo/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/knife4j-demo/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/knife4j-demo/.idea/compiler.xml b/knife4j-demo/.idea/compiler.xml
new file mode 100644
index 0000000..8adfac0
--- /dev/null
+++ b/knife4j-demo/.idea/compiler.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/.idea/inspectionProfiles/Project_Default.xml b/knife4j-demo/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6560a98
--- /dev/null
+++ b/knife4j-demo/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/.idea/jarRepositories.xml b/knife4j-demo/.idea/jarRepositories.xml
new file mode 100644
index 0000000..2d9362f
--- /dev/null
+++ b/knife4j-demo/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/.idea/misc.xml b/knife4j-demo/.idea/misc.xml
new file mode 100644
index 0000000..3ccb27b
--- /dev/null
+++ b/knife4j-demo/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/.idea/vcs.xml b/knife4j-demo/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/knife4j-demo/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/knife4j-demo.iml b/knife4j-demo/knife4j-demo.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/knife4j-demo/knife4j-demo.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/knife4j-demo/pom.xml b/knife4j-demo/pom.xml
new file mode 100644
index 0000000..c3694d6
--- /dev/null
+++ b/knife4j-demo/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+ org.example
+ knife4j-demo
+ 1.0-SNAPSHOT
+
+
+
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+
+ 2.0.2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 2.2.5.RELEASE
+
+
+
\ No newline at end of file
diff --git a/knife4j-demo/src/main/java/com/leosanqing/demo/App.java b/knife4j-demo/src/main/java/com/leosanqing/demo/App.java
new file mode 100644
index 0000000..72af763
--- /dev/null
+++ b/knife4j-demo/src/main/java/com/leosanqing/demo/App.java
@@ -0,0 +1,18 @@
+package com.leosanqing.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/5 上午9:37
+ * @Package: com.leosanqing.demo
+ * @Description: 启动类
+ * @Version: 1.0
+ */
+@SpringBootApplication
+public class App {
+ public static void main(String[] args) {
+ SpringApplication.run(App.class);
+ }
+}
diff --git a/knife4j-demo/src/main/java/com/leosanqing/demo/config/SwaggerConfiguration.java b/knife4j-demo/src/main/java/com/leosanqing/demo/config/SwaggerConfiguration.java
new file mode 100644
index 0000000..3177333
--- /dev/null
+++ b/knife4j-demo/src/main/java/com/leosanqing/demo/config/SwaggerConfiguration.java
@@ -0,0 +1,53 @@
+package com.leosanqing.demo.config;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+@EnableKnife4j
+@Import(BeanValidatorPluginsConfiguration.class)
+public class SwaggerConfiguration {
+
+
+ @Bean(value = "defaultApi2")
+ public Docket defaultApi2() {
+ Docket docket=new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(apiInfo())
+ //分组名称
+ .groupName("2.X版本")
+ .select()
+ //这里指定Controller扫描包路径
+ .apis(RequestHandlerSelectors.basePackage("com.leosanqing.demo.controller"))
+ .paths(PathSelectors.any())
+ .build();
+ return docket;
+ }
+
+
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .title("knife4j-demo接口API") // 标题
+ .contact(new Contact("leosanqing",
+ "https://github.com/leosanqing/Java-Notes",
+ "stormleo@qq.com")) // 联系人
+ .version("1.0.1")
+ .termsOfServiceUrl("https://github.com/leosanqing/Java-Notes") // 网站地址
+ .description("knife4j-demo API") // 描述
+ .build();
+
+
+ }
+}
\ No newline at end of file
diff --git a/knife4j-demo/src/main/java/com/leosanqing/demo/controller/TestController.java b/knife4j-demo/src/main/java/com/leosanqing/demo/controller/TestController.java
new file mode 100644
index 0000000..c42d2e2
--- /dev/null
+++ b/knife4j-demo/src/main/java/com/leosanqing/demo/controller/TestController.java
@@ -0,0 +1,34 @@
+package com.leosanqing.demo.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author: rtliu
+ * @Date: 2020/6/5 上午9:33
+ * @Package: com.leosanqing.demo.controller
+ * @Description: 测试
+ * @Version: 1.0
+ */
+@RestController
+@Api(value = "购物车相关接口api", tags = {"用于购物车相关操作"})
+public class TestController {
+
+ @GetMapping("/app")
+ @ApiOperation(value = "查询购物车", notes = "查询购物车", httpMethod = "GET")
+
+ public String queryData(@RequestParam String cartId){
+ return cartId;
+ }
+
+ @PostMapping("cart")
+ @ApiOperation(value = "添加购物车", notes = "添加购物车", httpMethod = "POST")
+
+ public void updateCart(){
+
+ }
+}
diff --git a/spring/.DS_Store b/spring/.DS_Store
index 920dba5..99c00cf 100644
Binary files a/spring/.DS_Store and b/spring/.DS_Store differ
diff --git a/spring/annotation/REDME.md b/spring/annotation/REDME.md
new file mode 100644
index 0000000..4e768b5
--- /dev/null
+++ b/spring/annotation/REDME.md
@@ -0,0 +1 @@
+#
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/$CACHE_FILE$ b/spring/annotation/annotation-test/.idea/$CACHE_FILE$
new file mode 100644
index 0000000..6cb8985
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/$CACHE_FILE$
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/$PRODUCT_WORKSPACE_FILE$ b/spring/annotation/annotation-test/.idea/$PRODUCT_WORKSPACE_FILE$
new file mode 100644
index 0000000..d4d7d1e
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/$PRODUCT_WORKSPACE_FILE$
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/compiler.xml b/spring/annotation/annotation-test/.idea/compiler.xml
new file mode 100644
index 0000000..3af4f73
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/compiler.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/inspectionProfiles/Project_Default.xml b/spring/annotation/annotation-test/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6560a98
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/misc.xml b/spring/annotation/annotation-test/.idea/misc.xml
new file mode 100644
index 0000000..3ccb27b
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/uiDesigner.xml b/spring/annotation/annotation-test/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/.idea/workspace.xml b/spring/annotation/annotation-test/.idea/workspace.xml
new file mode 100644
index 0000000..95a3dd3
--- /dev/null
+++ b/spring/annotation/annotation-test/.idea/workspace.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1574432207505
+
+
+ 1574432207505
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/src/main/java/Test.java
+ 131
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/annotation-test.iml b/spring/annotation/annotation-test/annotation-test.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/spring/annotation/annotation-test/annotation-test.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/pom.xml b/spring/annotation/annotation-test/pom.xml
new file mode 100644
index 0000000..85b040f
--- /dev/null
+++ b/spring/annotation/annotation-test/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+ com.leosanqing.test
+ annotation-test
+ 1.0-SNAPSHOT
+
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.11
+
+
+
\ No newline at end of file
diff --git a/spring/annotation/annotation-test/src/main/java/Column.java b/spring/annotation/annotation-test/src/main/java/Column.java
new file mode 100644
index 0000000..1ff897e
--- /dev/null
+++ b/spring/annotation/annotation-test/src/main/java/Column.java
@@ -0,0 +1,14 @@
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-11-22 22:24
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Column {
+ String value();
+}
diff --git a/spring/annotation/annotation-test/src/main/java/Table.java b/spring/annotation/annotation-test/src/main/java/Table.java
new file mode 100644
index 0000000..2040d05
--- /dev/null
+++ b/spring/annotation/annotation-test/src/main/java/Table.java
@@ -0,0 +1,14 @@
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-11-22 22:24
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Table {
+ String value();
+}
diff --git a/spring/annotation/annotation-test/src/main/java/Test.java b/spring/annotation/annotation-test/src/main/java/Test.java
new file mode 100644
index 0000000..2ede80b
--- /dev/null
+++ b/spring/annotation/annotation-test/src/main/java/Test.java
@@ -0,0 +1,182 @@
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.sql.*;
+
+/**
+ * @Author: leosanqing
+ * @Date: 2019-11-22 22:17
+ */
+public class Test {
+
+ static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
+ static final String DB_URL = "jdbc:mysql://localhost:3306/guns";
+ static final String USER = "root";
+ static final String PASS = "root";
+
+ public static void main(String[] args) {
+ User user1 = new User();
+ user1.setId(1);
+
+ User user2 = new User();
+ user2.setAge(22);
+
+ User user3 = new User();
+ user3.setEmail("leosanqing@qq.com,pipi@gmail.com,zs@qq.com");
+
+
+ query(user1);
+ query(user2);
+ query(user3);
+
+ }
+
+ /**
+ * 根据给的值,查询节点
+ *
+ * @param user
+ * @return
+ */
+ private static String convert2Sql(User user) {
+ StringBuilder buffer = new StringBuilder();
+
+ // 获取 User的字节码,便于之后反射获取想要的值
+ Class extends User> clazz = user.getClass();
+
+ //判断是否存在这个注解
+ boolean isExist = clazz.isAnnotationPresent(Table.class);
+ if (!isExist) {
+ return null;
+ }
+
+ // 获得表名
+ Table table = clazz.getAnnotation(Table.class);
+ String tableName = table.value();
+
+ // where 1 = 1 防止查询语句崩溃
+ buffer.append("select * from ").append(tableName).append(" where 1 = 1");
+
+ // 遍历所有的字段,判断是否有值
+ // 注意这个 getDeclaredFields 和 getFields的区别。前者不包括继承来的字段
+ Field[] fields = clazz.getDeclaredFields();
+// Field[] fields1 = clazz.getFields();
+
+ for (Field field : fields) {
+ // 判断是否是数据库中的字段
+ boolean fieldExist = field.isAnnotationPresent(Column.class);
+ if (!fieldExist) {
+ continue;
+ }
+
+ Object value = null;
+ // 获取字段的get方法,因为get方法都是get+首字母大写的字段名
+ String getMethodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
+ try {
+ Method method = clazz.getMethod(getMethodName);
+ value = method.invoke(user);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ // 获取到字段的注解的名字
+ Column fieldAnnotation = field.getAnnotation(Column.class);
+ String fieldAnnotationName = fieldAnnotation.value();
+
+
+ // 拼接sql
+ // 如果没有获取到值
+ if (value == null
+ || (value instanceof Integer && (Integer) value == 0)) {
+ continue;
+ } else if (value instanceof String) {
+ if (((String) value).contains(",")) {
+ String[] strs = ((String) value).split(",");
+ buffer.append(" and ").append(fieldAnnotationName).append(" in (");
+ for (String str : strs) {
+ buffer.append("'").append(str).append("'").append(",");
+ }
+ // 删除最后一个 逗号
+ if (',' == buffer.charAt(buffer.length() - 1)) {
+ buffer.deleteCharAt(buffer.length() - 1);
+ }
+ buffer.append(")");
+ } else {
+ buffer.append(" and ").append(fieldAnnotationName).append(" = '").append(value).append(" '");
+
+ }
+ } else if (value instanceof Integer) {
+ buffer.append(" and ").append(fieldAnnotationName).append(" = ").append(value);
+
+ }
+
+ }
+ return buffer.toString();
+ }
+
+
+ private static void query(User user) {
+ Connection conn = null;
+ Statement stmt = null;
+ try {
+ // 注册 JDBC 驱动
+ Class.forName(JDBC_DRIVER);
+
+ // 打开链接
+ System.out.println("连接数据库...");
+ conn = DriverManager.getConnection(DB_URL, USER, PASS);
+
+ // 执行查询
+ System.out.println(" 实例化Statement对象...");
+ stmt = conn.createStatement();
+ String sql = convert2Sql(user);
+
+ ResultSet rs = stmt.executeQuery(sql);
+
+ // 展开结果集数据库
+ while (rs.next()) {
+ // 通过字段检索
+ int id = rs.getInt("id");
+ String userName = rs.getString("user_name");
+ String nickName = rs.getString("nick_name");
+ String age = rs.getString("age");
+ String phone = rs.getString("phone");
+ String email = rs.getString("email");
+
+ // 输出数据
+ System.out.print("ID: " + id);
+ System.out.print(", username: " + userName);
+ System.out.print(", age: " + age);
+ System.out.print(", nickName: " + nickName);
+ System.out.print(", phone: " + phone);
+ System.out.print(", email: " + email);
+ System.out.print("\n");
+ }
+ // 完成后关闭
+ rs.close();
+ stmt.close();
+ conn.close();
+ } catch (SQLException se) {
+ // 处理 JDBC 错误
+ se.printStackTrace();
+ } catch (Exception e) {
+ // 处理 Class.forName 错误
+ e.printStackTrace();
+ } finally {
+ // 关闭资源
+ try {
+ if (stmt != null) {
+ stmt.close();
+ }
+ } catch (SQLException ignored) {
+ }// 什么都不做
+ try {
+ if (conn != null) {
+ conn.close();
+ }
+ } catch (SQLException se) {
+ se.printStackTrace();
+ }
+ }
+
+ }
+}
+
diff --git a/spring/annotation/annotation-test/src/main/java/User.java b/spring/annotation/annotation-test/src/main/java/User.java
new file mode 100644
index 0000000..779a8cd
--- /dev/null
+++ b/spring/annotation/annotation-test/src/main/java/User.java
@@ -0,0 +1,74 @@
+/**
+ * @Author: leosanqing
+ * @Date: 2019-11-22 21:58
+ */
+@Table("user")
+public class User {
+ @Column("id")
+ private int id;
+
+ @Column("user_name")
+ private String userName;
+
+ @Column("nick_name")
+ private String nickName;
+
+ @Column("age")
+ private int age;
+
+ @Column("email")
+ private String email;
+
+ @Column("phone")
+ private String phone;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getNickName() {
+ return nickName;
+ }
+
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+
+}
diff --git a/spring/annotation/annotation-test/target/classes/Column.class b/spring/annotation/annotation-test/target/classes/Column.class
new file mode 100644
index 0000000..863c716
Binary files /dev/null and b/spring/annotation/annotation-test/target/classes/Column.class differ
diff --git a/spring/annotation/annotation-test/target/classes/Table.class b/spring/annotation/annotation-test/target/classes/Table.class
new file mode 100644
index 0000000..75cde08
Binary files /dev/null and b/spring/annotation/annotation-test/target/classes/Table.class differ
diff --git a/spring/annotation/annotation-test/target/classes/Test.class b/spring/annotation/annotation-test/target/classes/Test.class
new file mode 100644
index 0000000..13d0b54
Binary files /dev/null and b/spring/annotation/annotation-test/target/classes/Test.class differ
diff --git a/spring/annotation/annotation-test/target/classes/User.class b/spring/annotation/annotation-test/target/classes/User.class
new file mode 100644
index 0000000..e3cdb9c
Binary files /dev/null and b/spring/annotation/annotation-test/target/classes/User.class differ
diff --git "a/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/README.md" "b/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/README.md"
new file mode 100644
index 0000000..262e3bd
--- /dev/null
+++ "b/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/README.md"
@@ -0,0 +1,588 @@
+# 什么是代理
+
+代理 的字面意思就是 代替别人处理事情。 举一个比较简单的例子,艺人要接商演,但是艺人时间宝贵,很忙,不可能什么都自己处理,所以有一个经济人的角色,这个经纪人就用来代替艺人处理一些不太重要的事情,比如商演薪酬洽谈,行程安排等等,**只有唱歌等演出才由艺人自己做**
+
+经纪人就是我们的代理类,而艺人就是 被代理的类。
+
+代理又分静态代理和动态代理
+
+# 静态代理
+
+**静态代理的代理对象和被代理对象在代理之前就已经确定,它们都实现相同的接口或继承相同的抽象类.**
+
+用个例子看下,某公司要*徐坤商演,但是收钱和洽谈这方面肯定交给 经纪人(代理类)来做,所以我们就这样写
+
+```java
+public interface Star {
+ /**
+ * 跳舞
+ */
+ void dance();
+}
+```
+
+```java
+public class Cxk implements Star {
+ @Override
+ public void dance() {
+ System.out.println("我是 练习时长两年半的练习生 " + this.getClass() + " ,我来 跳舞....");
+ }
+}
+```
+
+```java
+public class CxkProxy implements Star {
+
+
+ private Star star;
+
+ // 或者直接写死
+// private Star star = new Cxk();
+
+ public CxkProxy(Star star){
+ this.star = star;
+ }
+
+ @Override
+ public void dance() {
+ System.out.println("... 我是 cxk 的经纪人, 跳舞前 收钱 ...");
+ star.dance();
+ }
+}
+```
+
+```java
+public class Company {
+ public static void main(String[] args) {
+
+ Star cxkProxy = new CxkProxy(new Cxk());
+ cxkProxy.dance();
+ }
+}
+```
+
+```
+输出结果
+... 我是 cxk 的经纪人, 跳舞前 收钱 ...
+我是 练习时长两年半的练习生 class com.leosanqing.proxy.static1.Cxk ,我来 跳舞....
+```
+
+
+
+我们看上面的调用,其实我们一直是找 经纪人这个角色来进行 dance ,但最后 他还是调用了 真正的 跳舞的人,。
+
+我们从这方面想一下我们的业务,我们只要 dance 这个业务(你可以想成其他实际业务,比如 扣库存),而 经纪人 的种种行为,我们可以看成是 在做业务之前 进行了 log 日志打印。相当于增强了 我们 之前的业务。这也是 Spring AOP Advise 所做的事。所以应该翻译成 **增强**更贴切语境。
+
+但是 Spring 不可能使用 静态代理,所以下面就要介绍 动态代理了
+
+# JDK 动态代理
+
+动态代理有两种,一种是 JDK 的动态代理,一种是 CGlib 的动态代理。我们看下他们两个分别是什么
+
+```java
+public class ZhangSan implements Star {
+
+ @Override
+ public void dance() {
+ System.out.println("我是 " + this.getClass().getName() +" 我来跳舞");
+ }
+}
+
+
+public class ZhangSanProxy implements InvocationHandler {
+ private Object target;
+
+ public Object newObject(Object o){
+ this.target = o;
+ return Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),this);
+ }
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ System.out.println("------ 我是张三经纪人,唱歌前先收钱 -------");
+ return method.invoke(target, args);
+ }
+}
+
+
+public class Test {
+ public static void main(String[] args) {
+ ZhangSanProxy zhangSanProxy = new ZhangSanProxy();
+ Star star = (Star) zhangSanProxy.newObject(new ZhangSan());
+ star.dance();
+ }
+}
+
+// 输出结果
+------ 我是张三经纪人,唱歌前先收钱 -------
+我是 com.leosanqing.proxy.dynamic.jdk.ZhangSan 我来跳舞
+```
+
+我们看到,代理类 实现了 InvocationHandler 这个接口,然后重写他的 invoke 方法,在这里我们添加了某些其他的业务,比如收钱
+
+当代码执行到 star.dance()方法时,他会调用 ZhangSanProxy 的 invoke 方法,这是为啥?,肯定是我们 的 `zhangSanProxy.newObject(new ZhangSan());`这里做了什么,我们看下源码
+
+## 走进源码
+
+```java
+@CallerSensitive
+public static Object newProxyInstance(ClassLoader loader,
+ Class>[] interfaces,
+ InvocationHandler h)
+ throws IllegalArgumentException
+{
+ Objects.requireNonNull(h);
+
+ final Class>[] intfs = interfaces.clone();
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
+ }
+
+ /*
+ * Look up or generate the designated proxy class
+ * 查找或生成指定的代理类,这个是生成的主要的方法
+ */
+ Class> cl = getProxyClass0(loader, intfs);
+
+ /*
+ * Invoke its constructor with the designated invocation handler.
+ */
+ try {
+ if (sm != null) {
+ checkNewProxyPermission(Reflection.getCallerClass(), cl);
+ }
+
+ final Constructor> cons = cl.getConstructor(constructorParams);
+ final InvocationHandler ih = h;
+ if (!Modifier.isPublic(cl.getModifiers())) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Void run() {
+ cons.setAccessible(true);
+ return null;
+ }
+ });
+ }
+ return cons.newInstance(new Object[]{h});
+ } catch (IllegalAccessException|InstantiationException e) {
+ throw new InternalError(e.toString(), e);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ } else {
+ throw new InternalError(t.toString(), t);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new InternalError(e.toString(), e);
+ }
+}
+```
+
+```java
+ /**
+ * Generate a proxy class. Must call the checkProxyAccess method
+ * to perform permission checks before calling this.
+ */
+ private static Class> getProxyClass0(ClassLoader loader,
+ Class>... interfaces) {
+ if (interfaces.length > 65535) {
+ throw new IllegalArgumentException("interface limit exceeded");
+ }
+
+ // If the proxy class defined by the given loader implementing
+ // the given interfaces exists, this will simply return the cached copy;
+ // otherwise, it will create the proxy class via the ProxyClassFactory
+ // 返回代理类,如果有缓存返回缓存,没有则创建
+ return proxyClassCache.get(loader, interfaces);
+ }
+```
+
+```java
+ /**
+ * Look-up the value through the cache. This always evaluates the
+ * {@code subKeyFactory} function and optionally evaluates
+ * {@code valueFactory} function if there is no entry in the cache for given
+ * pair of (key, subKey) or the entry has already been cleared.
+ *
+ * @param key possibly null key
+ * @param parameter parameter used together with key to create sub-key and
+ * value (should not be null)
+ * @return the cached value (never null)
+ * @throws NullPointerException if {@code parameter} passed in or
+ * {@code sub-key} calculated by
+ * {@code subKeyFactory} or {@code value}
+ * calculated by {@code valueFactory} is null.
+ */
+ public V get(K key, P parameter) {
+ Objects.requireNonNull(parameter);
+
+ expungeStaleEntries();
+
+ // 能不能从缓存中获取对象,这里使用的是 弱引用,可能会被内存回收
+ Object cacheKey = CacheKey.valueOf(key, refQueue);
+
+ // lazily install the 2nd level valuesMap for the particular cacheKey
+ ConcurrentMap> valuesMap = map.get(cacheKey);
+ if (valuesMap == null) {
+ //putIfAbsent这个方法在key不存在的时候加入一个值,如果key存在就不放入
+ ConcurrentMap> oldValuesMap
+ = map.putIfAbsent(cacheKey,
+ valuesMap = new ConcurrentHashMap<>());
+ if (oldValuesMap != null) {
+ valuesMap = oldValuesMap;
+ }
+ }
+
+ // create subKey and retrieve the possible Supplier stored by that
+ // subKey from valuesMap
+ Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
+ Supplier supplier = valuesMap.get(subKey);
+ Factory factory = null;
+
+ // 一直循环,直到生成好对象并返回
+ while (true) {
+ if (supplier != null) {
+ // supplier might be a Factory or a CacheValue instance
+ // 在这里是返回
+ V value = supplier.get();
+ if (value != null) {
+ return value;
+ }
+ }
+ // else no supplier in cache
+ // or a supplier that returned null (could be a cleared CacheValue
+ // or a Factory that wasn't successful in installing the CacheValue)
+
+ // lazily construct a Factory
+ //
+ if (factory == null) {
+ factory = new Factory(key, parameter, subKey, valuesMap);
+ }
+
+ if (supplier == null) {
+ supplier = valuesMap.putIfAbsent(subKey, factory);
+ if (supplier == null) {
+ // successfully installed Factory
+ supplier = factory;
+ }
+ // else retry with winning supplier
+ } else {
+ if (valuesMap.replace(subKey, supplier, factory)) {
+ // successfully replaced
+ // cleared CacheEntry / unsuccessful Factory
+ // with our Factory
+ supplier = factory;
+ } else {
+ // retry with current supplier
+ supplier = valuesMap.get(subKey);
+ }
+ }
+ }
+ }
+```
+
+```java
+// 我们会从上一步 的 V value = supplier.get(); 进入到这里,这里就是真正生成代理类的地方
+
+private static final class ProxyClassFactory
+ implements BiFunction[], Class>>
+{
+ // prefix for all proxy class names
+ private static final String proxyClassNamePrefix = "$Proxy";
+
+ // next number to use for generation of unique proxy class names
+ private static final AtomicLong nextUniqueNumber = new AtomicLong();
+
+ @Override
+ public Class> apply(ClassLoader loader, Class>[] interfaces) {
+
+ Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
+ for (Class> intf : interfaces) {
+ /*
+ * Verify that the class loader resolves the name of this
+ * interface to the same Class object.
+ */
+ Class> interfaceClass = null;
+ try {
+ interfaceClass = Class.forName(intf.getName(), false, loader);
+ } catch (ClassNotFoundException e) {
+ }
+ if (interfaceClass != intf) {
+ throw new IllegalArgumentException(
+ intf + " is not visible from class loader");
+ }
+ /*
+ * Verify that the Class object actually represents an
+ * interface.
+ */
+ if (!interfaceClass.isInterface()) {
+ throw new IllegalArgumentException(
+ interfaceClass.getName() + " is not an interface");
+ }
+ /*
+ * Verify that this interface is not a duplicate.
+ */
+ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
+ throw new IllegalArgumentException(
+ "repeated interface: " + interfaceClass.getName());
+ }
+ }
+
+ String proxyPkg = null; // package to define proxy class in
+ int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
+
+ /*
+ * Record the package of a non-public proxy interface so that the
+ * proxy class will be defined in the same package. Verify that
+ * all non-public proxy interfaces are in the same package.
+ */
+ for (Class> intf : interfaces) {
+ int flags = intf.getModifiers();
+ if (!Modifier.isPublic(flags)) {
+ accessFlags = Modifier.FINAL;
+ String name = intf.getName();
+ int n = name.lastIndexOf('.');
+ String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
+ if (proxyPkg == null) {
+ proxyPkg = pkg;
+ } else if (!pkg.equals(proxyPkg)) {
+ throw new IllegalArgumentException(
+ "non-public interfaces from different packages");
+ }
+ }
+ }
+
+ if (proxyPkg == null) {
+ // if no non-public proxy interfaces, use com.sun.proxy package
+ proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
+ }
+
+ /*
+ * Choose a name for the proxy class to generate.
+ * 生成的代理类的名称
+ */
+ long num = nextUniqueNumber.getAndIncrement();
+ String proxyName = proxyPkg + proxyClassNamePrefix + num;
+
+ /*
+ * Generate the specified proxy class.
+ */
+ byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
+ proxyName, interfaces, accessFlags);
+ try {
+ return defineClass0(loader, proxyName,
+ proxyClassFile, 0, proxyClassFile.length);
+ } catch (ClassFormatError e) {
+ /*
+ * A ClassFormatError here means that (barring bugs in the
+ * proxy class generation code) there was some other
+ * invalid aspect of the arguments supplied to the proxy
+ * class creation (such as virtual machine limitations
+ * exceeded).
+ */
+ throw new IllegalArgumentException(e.toString());
+ }
+ }
+}
+```
+
+```java
+/*
+ * Generate the specified proxy class.
+ * 这里是重点,这里生成代理类的Class文件
+ */
+byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
+ proxyName, interfaces, accessFlags);
+```
+
+后面就看不到源码了,只能看到编译优化好的代码
+
+```java
+public static byte[] generateProxyClass(final String var0, Class>[] var1, int var2) {
+ ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
+ // 这里生成文件
+ final byte[] var4 = var3.generateClassFile();
+ if (saveGeneratedFiles) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Void run() {
+ try {
+ int var1 = var0.lastIndexOf(46);
+ Path var2;
+ if (var1 > 0) {
+ Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
+ Files.createDirectories(var3);
+ var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
+ } else {
+ var2 = Paths.get(var0 + ".class");
+ }
+
+ Files.write(var2, var4, new OpenOption[0]);
+ return null;
+ } catch (IOException var4x) {
+ throw new InternalError("I/O exception saving generated file: " + var4x);
+ }
+ }
+ });
+ }
+
+ return var4;
+}
+```
+
+我们看到代理对象的类型是 
+
+这个名字在哪里生成的,可以看看前面两三个类,我有一行注释
+
+最后绑定完之后,我们看 Star 生成的class 文件
+
+```java
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+import com.leosanqing.proxy.Star;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+
+public final class zhangSanProxy extends Proxy implements Star {
+ private static Method m1;
+ private static Method m3;
+ private static Method m2;
+ private static Method m0;
+
+ public zhangSanProxy(InvocationHandler var1) throws {
+ super(var1);
+ }
+
+ public final boolean equals(Object var1) throws {
+ try {
+ return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
+ } catch (RuntimeException | Error var3) {
+ throw var3;
+ } catch (Throwable var4) {
+ throw new UndeclaredThrowableException(var4);
+ }
+ }
+
+ public final void dance() throws {
+ try {
+ super.h.invoke(this, m3, (Object[])null);
+ } catch (RuntimeException | Error var2) {
+ throw var2;
+ } catch (Throwable var3) {
+ throw new UndeclaredThrowableException(var3);
+ }
+ }
+
+ public final String toString() throws {
+ try {
+ return (String)super.h.invoke(this, m2, (Object[])null);
+ } catch (RuntimeException | Error var2) {
+ throw var2;
+ } catch (Throwable var3) {
+ throw new UndeclaredThrowableException(var3);
+ }
+ }
+
+ public final int hashCode() throws {
+ try {
+ return (Integer)super.h.invoke(this, m0, (Object[])null);
+ } catch (RuntimeException | Error var2) {
+ throw var2;
+ } catch (Throwable var3) {
+ throw new UndeclaredThrowableException(var3);
+ }
+ }
+
+ static {
+ try {
+ m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
+ m3 = Class.forName("com.leosanqing.proxy.Star").getMethod("dance");
+ m2 = Class.forName("java.lang.Object").getMethod("toString");
+ m0 = Class.forName("java.lang.Object").getMethod("hashCode");
+ } catch (NoSuchMethodException var2) {
+ throw new NoSuchMethodError(var2.getMessage());
+ } catch (ClassNotFoundException var3) {
+ throw new NoClassDefFoundError(var3.getMessage());
+ }
+ }
+}
+
+```
+
+我们看到 他的 dance 方法,调用了`super.h.invoke(this, m3, (Object[])null);` 而那个 h 就是我们的`ZhangSanProxy`,然后就有了 我们写的 `ZhangSanProxy.invoke()`里面的内容
+
+# CGlib
+
+```java
+public class LiSi {
+ public void dance() {
+ System.out.println("我是 "+this.getClass().getName() + ", 我来唱歌");
+ }
+}
+
+
+public class LiSiProxy implements MethodInterceptor {
+
+ public static Object createProxyObject(Object o){
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(o.getClass());
+ enhancer.setCallback(new LiSiProxy());
+ return enhancer.create();
+ }
+
+ @Override
+ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
+ System.out.println("我是李四经纪人,演出前先收钱");
+ methodProxy.invokeSuper(o, objects);
+ return null;
+ }
+}
+
+
+
+public class Test {
+ public static void main(String[] args) {
+ LiSi proxyObject = (LiSi)LiSiProxy.createProxyObject(new LiSi());
+ proxyObject.dance();
+ }
+}
+
+
+我是李四经纪人,演出前先收钱
+我是 com.leosanqing.proxy.dynamic.cglib.LiSi$$EnhancerByCGLIB$$d5e54c2b, 我来唱歌
+```
+
+
+
+在使用 CGlib 的时候,**我们并没有 使用 Star 接口**,这也是 JDK 动态代理和 CGlib 的主要区别,
+
+
+
+# 区别
+
+1. JDK 动态代理只能代理实现了接口的类,没有实现接口的类是不能使用 JDK 动态代理的
+2. CGlib 是对类进行代理,运行时动态生成被代理类的子类 拦截父类的方法调用,所以类和方法不能声明成 final 类,不然会报错 `Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class com.leosanqing.proxy.dynamic.cglib.LiSi`
+
+# 结合Spring
+
+做Javaweb 项目,都是 三层结构,controller、service、dao,一层调用一层,但是我们在创建 service的时候,总是要先生成一个 ServiceInterface 然后再编写他的实现类,为什么会这样?难道不能不这样?
+
+**当然可以不这样**,不过这样子是因为 Spring 他 可以采用 CGlib 进行AOP,如果没有 CGlib,那么肯定要有 接口才行
+
+早期由于 Spring 只有 JDK的动态代理,所以必须 要写接口,然后接口实现,甚至你在 controller 层注入 的时候都不能这样写
+
+```java
+@Autowired
+private ServiceImpl servcieImpl
+```
+
+如果你这样,他会直接报错,因为他是用的是 JDK 的动态代理,你只能注入他的接口,而不能注入他的实现
+
+好在现在 Spring 引入了 CGlib,我们如果项目不大,或者不对外交互,可以少去 Service 的 interface 层。
+
+我们有一个项目就没有 interface层,直接编写他的实现类 `public class DealService extends ServiceImpl `,配合Mybatis-plus 直接进行快速开发
+
diff --git "a/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/img/Xnip2020-09-28_15-06-45.jpg" "b/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/img/Xnip2020-09-28_15-06-45.jpg"
new file mode 100644
index 0000000..a152f5a
Binary files /dev/null and "b/spring/aop/JDK\345\222\214CGlib\345\212\250\346\200\201\344\273\243\347\220\206/img/Xnip2020-09-28_15-06-45.jpg" differ
diff --git "a/spring/ioc/bean\347\232\204\345\210\235\345\247\213\345\214\226/REDME.md" "b/spring/ioc/bean\347\232\204\345\210\235\345\247\213\345\214\226/REDME.md"
new file mode 100644
index 0000000..f295bc3
--- /dev/null
+++ "b/spring/ioc/bean\347\232\204\345\210\235\345\247\213\345\214\226/REDME.md"
@@ -0,0 +1,1766 @@
+Spring IOC 容器
+
+构建一个 IOC 容器
+
+```java
+public class App {
+ public static void main(String[] args) {
+ // 用我们的配置文件来启动一个 ApplicationContext
+
+
+ // 使用注解配置
+ ann();
+ // 使用XML 配置
+ xml();
+
+ }
+
+ private static void xml() {
+ ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
+
+
+ System.out.println("context 启动成功");
+
+
+ // 从 context 中取出我们的 Bean,而不是用 new MessageServiceImpl() 这种方式
+ MessageService messageService = context.getBean(MessageService.class);
+ // 这句将输出: hello world
+ System.out.println(messageService.getMessage());
+ }
+
+ private static void ann(){
+ AnnotationConfigApplicationContext annotationConfigApplicationContext =
+ new AnnotationConfigApplicationContext(SpringConfiguration.class);
+ HelloWorldService bean = (HelloWorldService) annotationConfigApplicationContext.getBean("userService");
+
+ bean.say();
+ }
+}
+
+
+
+public interface MessageService {
+ String getMessage();
+}
+
+
+public class MessageServiceImpl implements MessageService {
+
+ public String getMessage() {
+ return "hello world";
+ }
+}
+```
+
+```javascript
+
+
+
+
+
+```
+
+
+
+我们肯定很好奇,Spring 到底是怎么把 各个 Bean 放在 容器中管理的,他是怎么生成的。那就跟着源码来看下他是怎么初始化各个类,然后又怎么对其属性进行赋值的吧
+
+
+
+我们就从 `App.class` 入手
+
+我们 new 了一个 `ClassPathXmlApplicationContext`, 这个 就是我们使用 XML 这种配置方式进行配置的时候加载的
+
+而 另一边 `AnnotationConfigApplicationContext` 这个 就是我们使用注解时调用的 容器了。
+
+我们先从 XML 开始,只是一开始处理的方式不同,后面调用的 还是一模一样的
+
+
+
+```java
+/**
+ * Create a new ClassPathXmlApplicationContext, loading the definitions
+ * from the given XML file and automatically refreshing the context.
+ * @param configLocation resource location
+ * @throws BeansException if context creation failed
+ */
+// 我们可以使用这个 创建或者刷新容器
+public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
+ this(new String[] {configLocation}, true, null);
+}
+```
+
+```java
+public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
+ throws BeansException {
+
+ super(parent);
+ // 设置 配置文件路径,再加上一些标点符号的处理
+ setConfigLocations(configLocations);
+ if (refresh) {
+ // 这个是核心方法
+ refresh();
+ }
+}
+```
+
+
+
+# 核心方法Refresh
+
+```java
+
+@Override
+public void refresh() throws BeansException, IllegalStateException {
+ // 上来先加个锁
+ synchronized (this.startupShutdownMonitor) {
+ // Prepare this context for refreshing.
+ // 1.准备工作 主要是 设置开始时间,检验xml文件,不是重点
+ prepareRefresh();
+
+ // 2.Tell the subclass to refresh the internal bean factory.
+ // 这一步比较关键,不仅解析了 XML, 还把每一个Bean 的名称(定义),放到容器中(以map的形式)
+ // 当然,这里只有定义,没有初始化,相当于你爸老早给你取好了名字,但是你还没有出生
+ ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
+
+ // 3.Prepare the bean factory for use in this context.
+ // 准备 Bean 容器
+ prepareBeanFactory(beanFactory);
+
+ try {
+ // 4.Allows post-processing of the bean factory in context subclasses.
+ postProcessBeanFactory(beanFactory);
+
+ // 5.Invoke factory processors registered as beans in the context.
+ invokeBeanFactoryPostProcessors(beanFactory);
+
+ // 6.Register bean processors that intercept bean creation.
+ registerBeanPostProcessors(beanFactory);
+
+ // 7.Initialize message source for this context.
+ // 初始化一些
+ initMessageSource();
+
+ // 8.Initialize event multicaster for this context.
+ // 初始化一些 事件广播
+ initApplicationEventMulticaster();
+
+ // 9.Initialize other special beans in specific context subclasses.
+ // 初始化 子类的一些东西
+ onRefresh();
+
+ // 10.Check for listener beans and register them.
+ // 注册事件监听器
+ registerListeners();
+
+
+ // 11.Instantiate all remaining (non-lazy-init) singletons.
+ // !!! 重点,初始化所有 非懒加载的单例
+ finishBeanFactoryInitialization(beanFactory);
+
+ // 12.Last step: publish corresponding event.
+ // 完成所有初始化信息
+ finishRefresh();
+ }
+```
+
+## 1. 创建 刷新前的准备工作
+
+```java
+/**
+ * Prepare this context for refreshing, setting its startup date and
+ * active flag as well as performing any initialization of property sources.
+ */
+protected void prepareRefresh() {
+ this.startupDate = System.currentTimeMillis();
+ this.closed.set(false);
+ this.active.set(true);
+
+ if (logger.isInfoEnabled()) {
+ logger.info("Refreshing " + this);
+ }
+
+ // Initialize any placeholder property sources in the context environment
+ initPropertySources();
+
+ // Validate that all properties marked as required are resolvable
+ // see ConfigurablePropertyResolver#setRequiredProperties
+ getEnvironment().validateRequiredProperties();
+
+ // Allow for the collection of early ApplicationEvents,
+ // to be published once the multicaster is available...
+ this.earlyApplicationEvents = new LinkedHashSet();
+}
+
+```
+
+## 2. 获得BeanFactory
+
+```java
+/**
+ * Tell the subclass to refresh the internal bean factory.
+ * @return the fresh BeanFactory instance
+ * @see #refreshBeanFactory()
+ * @see #getBeanFactory()
+ */
+protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
+ refreshBeanFactory();
+ ConfigurableListableBeanFactory beanFactory = getBeanFactory();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
+ }
+ return beanFactory;
+}
+```
+
+```java
+/**
+ * This implementation performs an actual refresh of this context's underlying
+ * bean factory, shutting down the previous bean factory (if any) and
+ * initializing a fresh bean factory for the next phase of the context's lifecycle.
+ */
+@Override
+protected final void refreshBeanFactory() throws BeansException {
+ // 如果已经创建过工厂了,就销毁,然后重新初始化。
+ // 没有就直接初始化
+ if (hasBeanFactory()) {
+ destroyBeans();
+ closeBeanFactory();
+ }
+ try {
+ // !!!!!!!
+ // 记住这个 DefaultListableBeanFactory 类,他很重要,等下说
+ DefaultListableBeanFactory beanFactory = createBeanFactory();
+ // 设置他的序列号
+ beanFactory.setSerializationId(getId());
+ // 自定义一些参数,如是否允许覆盖 是否允许循环依赖
+ customizeBeanFactory(beanFactory);
+ // 加载 BeanDefinition
+ loadBeanDefinitions(beanFactory);
+ synchronized (this.beanFactoryMonitor) {
+ this.beanFactory = beanFactory;
+ }
+ }
+ catch (IOException ex) {
+ throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
+ }
+}
+```
+
+
+
+虽然 ApplicationContext 继承自 BeanFactory,但是 **他并不应该被理解为 BeanFactory 的实现(子类)**,而是他内部实例化了一个 BeanFactory(DefaultListableBeanFactory),这个类很厉害,之后所有的 BeanFactory 相关的操作都是委托给他来干的
+
+我们看图,他左边 继承自 `ConfigurableListableBeanFactory` ,而这个接口实现了 `BeanFactory`接口的 下一层的 所有的接口(三个接口)。 而他 右边 通过 实现 `AbstractAutowireCapableBeanFactory` 打通了右边所有的接口。所以`DefaultListableBeanFactory`他真的很牛皮
+
+而我们 使用 ApplicationContext 的时候 能通过 `context.getAutowireCapableBeanFactory()`直接拿到 `AutowireCapableBeanFactory`,然后再经过转型就能拿到 `DefaultListableBeanFactory`。
+
+### BeanDefinition
+
+既然是 BeanFactory ,那么 我们的 Bean 是什么东西
+
+spring 他不会直接管理你定义的 class 或者你自己定义的 bean,他会把他们转换成 BeanDefinition ,然后再用容器管理他们。这个 BeanDefinition 对象 存储了很多很多东西,如是否懒加载,是否单例,依赖哪些类,等等
+
+```java
+public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
+
+ String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
+
+ String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
+
+ int ROLE_APPLICATION = 0;
+ int ROLE_SUPPORT = 1;
+ int ROLE_INFRASTRUCTURE = 2;
+
+
+ // Modifiable attributes
+
+ void setParentName(String parentName);
+ String getParentName();
+
+ void setBeanClassName(String beanClassName);
+ String getBeanClassName();
+
+ // 作用域
+ void setScope(String scope);
+ String getScope();
+
+ // 是否懒加载
+ void setLazyInit(boolean lazyInit);
+ boolean isLazyInit();
+
+ // 依赖的类
+ void setDependsOn(String... dependsOn);
+ String[] getDependsOn();
+
+ // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
+ // 如果根据名称注入,即使这边设置了 false,也是可以的
+ void setAutowireCandidate(boolean autowireCandidate);
+ boolean isAutowireCandidate();
+
+ void setPrimary(boolean primary);
+ boolean isPrimary();
+
+ void setFactoryBeanName(String factoryBeanName);
+ String getFactoryBeanName();
+
+ void setFactoryMethodName(String factoryMethodName);
+ String getFactoryMethodName();
+
+ ConstructorArgumentValues getConstructorArgumentValues();
+
+ MutablePropertyValues getPropertyValues();
+
+ // Read-only attributes
+
+ boolean isSingleton();
+
+ boolean isPrototype();
+
+ boolean isAbstract();
+
+ int getRole();
+
+ String getDescription();
+
+ String getResourceDescription();
+
+ BeanDefinition getOriginatingBeanDefinition();
+
+}
+```
+
+```java
+/**
+ * Loads the bean definitions via an XmlBeanDefinitionReader.
+ * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
+ * @see #initBeanDefinitionReader
+ * @see #loadBeanDefinitions
+ */
+@Override
+protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
+ // Create a new XmlBeanDefinitionReader for the given BeanFactory.
+ // 实例化一个 XmlBeanDefinition 解析器
+ XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
+
+ // Configure the bean definition reader with this context's
+ // resource loading environment.
+ beanDefinitionReader.setEnvironment(this.getEnvironment());
+ beanDefinitionReader.setResourceLoader(this);
+ beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
+
+ // Allow a subclass to provide custom initialization of the reader,
+ // then proceed with actually loading the bean definitions.
+ initBeanDefinitionReader(beanDefinitionReader);
+
+ loadBeanDefinitions(beanDefinitionReader);
+}
+
+
+/**
+ * Load the bean definitions with the given XmlBeanDefinitionReader.
+ * The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory}
+ * method; hence this method is just supposed to load and/or register bean definitions.
+ * @param reader the XmlBeanDefinitionReader to use
+ * @throws BeansException in case of bean registration errors
+ * @throws IOException if the required XML document isn't found
+ * @see #refreshBeanFactory
+ * @see #getConfigLocations
+ * @see #getResources
+ * @see #getResourcePatternResolver
+ */
+ protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
+ Resource[] configResources = getConfigResources();
+ // 往下看,最后这两个都会走到 下面这个方法里面
+ if (configResources != null) {
+ reader.loadBeanDefinitions(configResources);
+ }
+ // 获取配置文件地址
+ String[] configLocations = getConfigLocations();
+ if (configLocations != null) {
+ reader.loadBeanDefinitions(configLocations);
+ }
+ }
+```
+
+```java
+@Override
+public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
+ Assert.notNull(locations, "Location array must not be null");
+ int counter = 0;
+ // 加载每个配置文件中的 配置信息
+ for (String location : locations) {
+ counter += loadBeanDefinitions(location);
+ }
+ // 返回 加载了 多少个 BeanDefinition
+ return counter;
+}
+
+@Override
+public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
+ return loadBeanDefinitions(location, null);
+}
+
+
+
+public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
+ ResourceLoader resourceLoader = getResourceLoader();
+ if (resourceLoader == null) {
+ throw new BeanDefinitionStoreException(
+ "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
+ }
+
+ if (resourceLoader instanceof ResourcePatternResolver) {
+ // Resource pattern matching available.
+ try {
+ Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
+ // 加载 BeanDefinition
+ int loadCount = loadBeanDefinitions(resources);
+ if (actualResources != null) {
+ for (Resource resource : resources) {
+ actualResources.add(resource);
+ }
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
+ }
+ return loadCount;
+ }
+ catch (IOException ex) {
+ throw new BeanDefinitionStoreException(
+ "Could not resolve bean definition resource pattern [" + location + "]", ex);
+ }
+ }
+ else {
+ // Can only load single resources by absolute URL.
+ Resource resource = resourceLoader.getResource(location);
+ int loadCount = loadBeanDefinitions(resource);
+ if (actualResources != null) {
+ actualResources.add(resource);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
+ }
+ return loadCount;
+ }
+}
+```
+
+
+
+// org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java
+
+```java
+
+@Override
+ public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
+ Assert.notNull(resources, "Resource array must not be null");
+ int counter = 0;
+ for (Resource resource : resources) {
+ counter += loadBeanDefinitions(resource);
+ }
+ return counter;
+ }
+
+
+ /**
+ * Load bean definitions from the specified XML file.
+ * @param resource the resource descriptor for the XML file
+ * @return the number of bean definitions found
+ * @throws BeanDefinitionStoreException in case of loading or parsing errors
+ */
+ @Override
+ public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
+ return loadBeanDefinitions(new EncodedResource(resource));
+ }
+
+
+public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
+ Assert.notNull(encodedResource, "EncodedResource must not be null");
+ if (logger.isInfoEnabled()) {
+ logger.info("Loading XML bean definitions from " + encodedResource.getResource());
+ }
+
+ Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
+ if (currentResources == null) {
+ currentResources = new HashSet(4);
+ this.resourcesCurrentlyBeingLoaded.set(currentResources);
+ }
+ if (!currentResources.add(encodedResource)) {
+ throw new BeanDefinitionStoreException(
+ "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
+ }
+ try {
+ InputStream inputStream = encodedResource.getResource().getInputStream();
+ try {
+ InputSource inputSource = new InputSource(inputStream);
+ if (encodedResource.getEncoding() != null) {
+ inputSource.setEncoding(encodedResource.getEncoding());
+ }
+ // !!!! 这里是重点
+ return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
+ }
+ finally {
+ inputStream.close();
+ }
+ }
+ catch (IOException ex) {
+ throw new BeanDefinitionStoreException(
+ "IOException parsing XML document from " + encodedResource.getResource(), ex);
+ }
+ finally {
+ currentResources.remove(encodedResource);
+ if (currentResources.isEmpty()) {
+ this.resourcesCurrentlyBeingLoaded.remove();
+ }
+ }
+ }
+```
+
+```java
+protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
+ throws BeanDefinitionStoreException {
+ try {
+ // 将 xml 解析成 Doc 文件
+ Document doc = doLoadDocument(inputSource, resource);
+ return registerBeanDefinitions(doc, resource);
+ }
+ catch (BeanDefinitionStoreException ex) {
+ throw ex;
+ }
+ catch (SAXParseException ex) {
+ throw new XmlBeanDefinitionStoreException(resource.getDescription(),
+ "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
+ }
+ catch (SAXException ex) {
+ throw new XmlBeanDefinitionStoreException(resource.getDescription(),
+ "XML document from " + resource + " is invalid", ex);
+ }
+ catch (ParserConfigurationException ex) {
+ throw new BeanDefinitionStoreException(resource.getDescription(),
+ "Parser configuration exception parsing XML from " + resource, ex);
+ }
+ catch (IOException ex) {
+ throw new BeanDefinitionStoreException(resource.getDescription(),
+ "IOException parsing XML document from " + resource, ex);
+ }
+ catch (Throwable ex) {
+ throw new BeanDefinitionStoreException(resource.getDescription(),
+ "Unexpected exception parsing XML document from " + resource, ex);
+ }
+}
+
+public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
+ BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
+ int countBefore = getRegistry().getBeanDefinitionCount();
+// 这
+ documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
+ // 加载后减去 之前的 就是加载了 几个
+ return getRegistry().getBeanDefinitionCount() - countBefore;
+ }
+```
+
+```java
+/**
+ * Register each bean definition within the given root {@code } element.
+ */
+protected void doRegisterBeanDefinitions(Element root) {
+ // Any nested elements will cause recursion in this method. In
+ // order to propagate and preserve default-* attributes correctly,
+ // keep track of the current (parent) delegate, which may be null. Create
+ // the new (child) delegate with a reference to the parent for fallback purposes,
+ // then ultimately reset this.delegate back to its original (parent) reference.
+ // this behavior emulates a stack of delegates without actually necessitating one.
+
+ // 我们看名字就知道,BeanDefinitionParserDelegate 必定是一个重要的类,它负责解析 Bean 定义,
+ // 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题,
+ // 因为 内部是可以定义 的,所以这个方法的 root 其实不一定就是 xml 的根节点,也可以是嵌套在里面的 节点,从源码分析的角度,我们当做根节点就好了
+ BeanDefinitionParserDelegate parent = this.delegate;
+ this.delegate = createDelegate(getReaderContext(), root, parent);
+
+ // 判断他是否是当前环境下的配置文件
+ if (this.delegate.isDefaultNamespace(root)) {
+ String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
+ if (StringUtils.hasText(profileSpec)) {
+ String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
+ profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
+ if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
+ "] not matching: " + getReaderContext().getResource());
+ }
+ return;
+ }
+ }
+ }
+
+ preProcessXml(root);
+ parseBeanDefinitions(root, this.delegate);
+ postProcessXml(root);
+
+ this.delegate = parent;
+}
+```
+
+```java
+/**
+ * Parse the elements at the root level in the document:
+ * "import", "alias", "bean".
+ * @param root the DOM root element of the document
+ */
+protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
+ if (delegate.isDefaultNamespace(root)) {
+ NodeList nl = root.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node node = nl.item(i);
+ if (node instanceof Element) {
+ Element ele = (Element) node;
+ if (delegate.isDefaultNamespace(ele)) {
+ // 解析 默认节点元素
+ parseDefaultElement(ele, delegate);
+ }
+ else {
+ delegate.parseCustomElement(ele);
+ }
+ }
+ }
+ }
+ else {
+ delegate.parseCustomElement(root);
+ }
+}
+
+
+// import alias bean beans 这几个标签 是默认的,如果不是这几个但又在 默认标签下,他是不会处理的
+private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
+ if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
+ importBeanDefinitionResource(ele);
+ }
+ else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
+ processAliasRegistration(ele);
+ }
+ else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
+ processBeanDefinition(ele, delegate);
+ }
+ else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
+ // recurse
+ doRegisterBeanDefinitions(ele);
+ }
+ }
+```
+
+### 解析xml中 Bean 标签
+
+```java
+/**
+ * Process the given bean element, parsing the bean definition
+ * and registering it with the registry.
+ */
+protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
+ // 生成 BeanDefinitionHolder 里面包含了 BeanDefinition 对象
+ BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
+ if (bdHolder != null) {
+ bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
+ try {
+ // Register the final decorated instance.
+ BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
+ }
+ catch (BeanDefinitionStoreException ex) {
+ getReaderContext().error("Failed to register bean definition with name '" +
+ bdHolder.getBeanName() + "'", ele, ex);
+ }
+ // Send registration event.
+ getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
+ }
+}
+```
+
+```java
+/**
+ * Parses the supplied {@code } element. May return {@code null}
+ * if there were errors during parse. Errors are reported to the
+ * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
+ */
+public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
+ String id = ele.getAttribute(ID_ATTRIBUTE);
+ String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
+ // 将名字按照 以下标点切分
+ // public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
+ List aliases = new ArrayList();
+ if (StringUtils.hasLength(nameAttr)) {
+ String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
+ aliases.addAll(Arrays.asList(nameArr));
+ }
+
+ String beanName = id;
+ // 如果 没有 id,但是有别名,就将别名中的第一个名字 作为beanName
+ if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
+ beanName = aliases.remove(0);
+ if (logger.isDebugEnabled()) {
+ logger.debug("No XML 'id' specified - using '" + beanName +
+ "' as bean name and " + aliases + " as aliases");
+ }
+ }
+
+ if (containingBean == null) {
+ // a.校验 名称是否唯一
+ checkNameUniqueness(beanName, aliases, ele);
+ }
+
+ // b.这个执行完 一个 BeanDefinition 对象就生成了,属性值那些都会在这里赋值处理
+ AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
+ if (beanDefinition != null) {
+ // 如果我们没有设置到 beanName
+ if (!StringUtils.hasText(beanName)) {
+ try {
+ if (containingBean != null) {
+ // 生成 beanName,{类名}#{第几个beanDefinition}
+ beanName = BeanDefinitionReaderUtils.generateBeanName(
+ beanDefinition, this.readerContext.getRegistry(), true);
+ }
+ else {
+ beanName = this.readerContext.generateBeanName(beanDefinition);
+ // Register an alias for the plain bean class name, if still possible,
+ // if the generator returned the class name plus a suffix.
+ // This is expected for Spring 1.2/2.0 backwards compatibility.
+ String beanClassName = beanDefinition.getBeanClassName();
+ if (beanClassName != null &&
+ beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
+ !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
+ aliases.add(beanClassName);
+ }
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("Neither XML 'id' nor 'name' specified - " +
+ "using generated bean name [" + beanName + "]");
+ }
+ }
+ catch (Exception ex) {
+ error(ex.getMessage(), ele);
+ return null;
+ }
+ }
+ String[] aliasesArray = StringUtils.toStringArray(aliases);
+ return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
+ }
+
+ return null;
+}
+```
+
+### a.校验名称的唯一性
+
+```java
+protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) {
+ String foundName = null;
+
+ if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
+ foundName = beanName;
+ }
+ if (foundName == null) {
+ foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);
+ }
+ if (foundName != null) {
+ error("Bean name '" + foundName + "' is already used in this element", beanElement);
+ }
+
+ this.usedNames.add(beanName);
+ this.usedNames.addAll(aliases);
+}
+```
+
+### b.生成BeanDefinition对象
+
+```java
+public AbstractBeanDefinition parseBeanDefinitionElement(
+ Element ele, String beanName, BeanDefinition containingBean) {
+
+ this.parseState.push(new BeanEntry(beanName));
+
+ String className = null;
+ if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
+ className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
+ }
+
+ try {
+ String parent = null;
+ if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
+ parent = ele.getAttribute(PARENT_ATTRIBUTE);
+ }
+ AbstractBeanDefinition bd = createBeanDefinition(className, parent);
+
+ parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
+ bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
+
+ parseMetaElements(ele, bd);
+ parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
+ parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
+
+ parseConstructorArgElements(ele, bd);
+ parsePropertyElements(ele, bd);
+ parseQualifierElements(ele, bd);
+
+ bd.setResource(this.readerContext.getResource());
+ bd.setSource(extractSource(ele));
+
+ return bd;
+ }
+ catch (ClassNotFoundException ex) {
+ error("Bean class [" + className + "] not found", ele, ex);
+ }
+ catch (NoClassDefFoundError err) {
+ error("Class that bean class [" + className + "] depends on not found", ele, err);
+ }
+ catch (Throwable ex) {
+ error("Unexpected failure during bean definition parsing", ele, ex);
+ }
+ finally {
+ this.parseState.pop();
+ }
+
+ return null;
+}
+```
+
+### 注册 Bean
+
+```java
+/**
+ * Process the given bean element, parsing the bean definition
+ * and registering it with the registry.
+ */
+protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
+ // 刚刚看过了,就是上面一坨
+ BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
+ if (bdHolder != null) {
+ bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
+ try {
+ // Register the final decorated instance.
+ // 注册 bean实例
+ BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
+ }
+ catch (BeanDefinitionStoreException ex) {
+ getReaderContext().error("Failed to register bean definition with name '" +
+ bdHolder.getBeanName() + "'", ele, ex);
+ }
+ // Send registration event.
+ getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
+ }
+}
+```
+
+```java
+@Override
+public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
+ throws BeanDefinitionStoreException {
+
+ Assert.hasText(beanName, "Bean name must not be empty");
+ Assert.notNull(beanDefinition, "BeanDefinition must not be null");
+
+ if (beanDefinition instanceof AbstractBeanDefinition) {
+ try {
+ ((AbstractBeanDefinition) beanDefinition).validate();
+ }
+ catch (BeanDefinitionValidationException ex) {
+ throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
+ "Validation of bean definition failed", ex);
+ }
+ }
+
+ BeanDefinition oldBeanDefinition;
+
+ // 如果之前已经有这个 名字
+ oldBeanDefinition = this.beanDefinitionMap.get(beanName);
+ if (oldBeanDefinition != null) {
+ // 如果不允许重载
+ if (!isAllowBeanDefinitionOverriding()) {
+ throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
+ "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
+ "': There is already [" + oldBeanDefinition + "] bound.");
+ }
+ // bean 等级 三个
+ else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
+ // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
+ if (this.logger.isWarnEnabled()) {
+ this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
+ "' with a framework-generated bean definition: replacing [" +
+ oldBeanDefinition + "] with [" + beanDefinition + "]");
+ }
+ }
+ // 新的覆盖旧的
+ else if (!beanDefinition.equals(oldBeanDefinition)) {
+ if (this.logger.isInfoEnabled()) {
+ this.logger.info("Overriding bean definition for bean '" + beanName +
+ "' with a different definition: replacing [" + oldBeanDefinition +
+ "] with [" + beanDefinition + "]");
+ }
+ }
+ else {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Overriding bean definition for bean '" + beanName +
+ "' with an equivalent definition: replacing [" + oldBeanDefinition +
+ "] with [" + beanDefinition + "]");
+ }
+ }
+ this.beanDefinitionMap.put(beanName, beanDefinition);
+ }
+ else {
+ // 判断是否有Bean 已经开始初始化
+ if (hasBeanCreationStarted()) {
+ // Cannot modify startup-time collection elements anymore (for stable iteration)
+ synchronized (this.beanDefinitionMap) {
+ this.beanDefinitionMap.put(beanName, beanDefinition);
+ List updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
+ updatedDefinitions.addAll(this.beanDefinitionNames);
+ updatedDefinitions.add(beanName);
+ this.beanDefinitionNames = updatedDefinitions;
+ if (this.manualSingletonNames.contains(beanName)) {
+ Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
+ updatedSingletons.remove(beanName);
+ this.manualSingletonNames = updatedSingletons;
+ }
+ }
+ }
+ else {
+ // Still in startup registration phase
+ // 放入map
+ this.beanDefinitionMap.put(beanName, beanDefinition);
+ this.beanDefinitionNames.add(beanName);
+ // 这是个 LinkedHashSet,代表的是手动注册的 singleton bean,
+ // 注意这里是 remove 方法,到这里的 Bean 当然不是手动注册的
+ // 手动指的是通过调用以下方法注册的 bean :
+ // registerSingleton(String beanName, Object singletonObject)
+ // 这不是重点,解释只是为了不让大家疑惑。Spring 会在后面"手动"注册一些 Bean,
+ // 如 "environment"、"systemProperties" 等 bean,我们自己也可以在运行时注册 Bean 到容器中的
+ this.manualSingletonNames.remove(beanName);
+ }
+ this.frozenBeanDefinitionNames = null;
+ }
+
+ if (oldBeanDefinition != null || containsSingleton(beanName)) {
+ resetBeanDefinition(beanName);
+ }
+}
+```
+
+------
+
+到目前为止,我们才相当于声明了 BeanDefinition ,才走完Refresh 中的 第二个方法 后面才是实例化他
+
+## 3.准备Bean容器
+
+```java
+/**
+ * Configure the factory's standard context characteristics,
+ * such as the context's ClassLoader and post-processors.
+ * @param beanFactory the BeanFactory to configure
+ */
+protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ // Tell the internal bean factory to use the context's class loader etc.
+ beanFactory.setBeanClassLoader(getClassLoader());
+ beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
+ beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
+
+ // Configure the bean factory with context callbacks.
+ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
+ beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
+ beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
+ beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
+ beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
+ beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
+ beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
+
+ // BeanFactory interface not registered as resolvable type in a plain factory.
+ // MessageSource registered (and found for autowiring) as a bean.
+ beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
+ beanFactory.registerResolvableDependency(ResourceLoader.class, this);
+ beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
+ beanFactory.registerResolvableDependency(ApplicationContext.class, this);
+
+ // Register early post-processor for detecting inner beans as ApplicationListeners.
+ beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
+
+ // Detect a LoadTimeWeaver and prepare for weaving, if found.
+ if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
+ beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
+ // Set a temporary ClassLoader for type matching.
+ beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
+ }
+
+ // 如果还没有注册 默认的 一些 bean ,spring会自动帮你注册
+ // Register default environment beans.
+ if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
+ beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
+ }
+ if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
+ beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
+ }
+ if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
+ beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
+ }
+}
+```
+
+## 11.实例化Bean
+
+这里是重点
+
+他会初始化所有 **非懒加载**的 **单例** 的Bean
+
+```java
+/**
+ * Finish the initialization of this context's bean factory,
+ * initializing all remaining singleton beans.
+ */
+protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
+ // Initialize conversion service for this context.
+ // 寻找并初始化 conversionService
+ if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
+ beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
+ beanFactory.setConversionService(
+ beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
+ }
+
+ // Register a default embedded value resolver if no bean post-processor
+ // (such as a PropertyPlaceholderConfigurer bean) registered any before:
+ // at this point, primarily for resolution in annotation attribute values.
+ if (!beanFactory.hasEmbeddedValueResolver()) {
+ beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
+ @Override
+ public String resolveStringValue(String strVal) {
+ return getEnvironment().resolvePlaceholders(strVal);
+ }
+ });
+ }
+
+ // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
+ // 初始化 LoadTimeWeaverAware 类型的 bean
+ String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
+ for (String weaverAwareName : weaverAwareNames) {
+ getBean(weaverAwareName);
+ }
+
+ // Stop using the temporary ClassLoader for type matching.
+ beanFactory.setTempClassLoader(null);
+
+ // Allow for caching all bean definition metadata, not expecting further changes.
+ // 马上就要进行 初始化了,防止再出现 bean的改变
+ beanFactory.freezeConfiguration();
+
+ // Instantiate all remaining (non-lazy-init) singletons.
+ beanFactory.preInstantiateSingletons();
+}
+```
+
+```java
+@Override
+public void preInstantiateSingletons() throws BeansException {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Pre-instantiating singletons in " + this);
+ }
+
+ // Iterate over a copy to allow for init methods which in turn register new bean definitions.
+ // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
+ List beanNames = new ArrayList(this.beanDefinitionNames);
+
+ // Trigger initialization of all non-lazy singleton beans...
+ for (String beanName : beanNames) {
+ // 合并父类中的配置信息
+ RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
+ // 如果不是抽象类 且 是单例 且 非懒加载
+ if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
+ // 处理 FactoryBean
+ if (isFactoryBean(beanName)) {
+ // FactoryBean 前面需要 加 & 符号
+ final FactoryBean> factory = (FactoryBean>) getBean(FACTORY_BEAN_PREFIX + beanName);
+ boolean isEagerInit;
+ if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
+ isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
+ public Boolean run() {
+ return ((SmartFactoryBean>) factory).isEagerInit();
+ }
+ }, getAccessControlContext());
+ }
+ else {
+ isEagerInit = (factory instanceof SmartFactoryBean &&
+ ((SmartFactoryBean>) factory).isEagerInit());
+ }
+ if (isEagerInit) {
+ getBean(beanName);
+ }
+ }
+ else {
+ // getBean 就进行了 初始化
+ getBean(beanName);
+ }
+ }
+ }
+
+ // Trigger post-initialization callback for all applicable beans...
+ for (String beanName : beanNames) {
+ Object singletonInstance = getSingleton(beanName);
+ if (singletonInstance instanceof SmartInitializingSingleton) {
+ final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
+ public Object run() {
+ smartSingleton.afterSingletonsInstantiated();
+ return null;
+ }
+ }, getAccessControlContext());
+ }
+ else {
+ smartSingleton.afterSingletonsInstantiated();
+ }
+ }
+ }
+}
+```
+
+```java
+// org.springframework.beans.factory.support.AbstractBeanFactory
+
+@Override
+public Object getBean(String name) throws BeansException {
+ return doGetBean(name, null, null, false);
+}
+
+
+
+/**
+ * Return an instance, which may be shared or independent, of the specified bean.
+ * @param name the name of the bean to retrieve
+ * @param requiredType the required type of the bean to retrieve
+ * @param args arguments to use when creating a bean instance using explicit arguments
+ * (only applied when creating a new instance as opposed to retrieving an existing one)
+ * @param typeCheckOnly whether the instance is obtained for a type check,
+ * not for actual use
+ * @return an instance of the bean
+ * @throws BeansException if the bean could not be created
+ */
+ @SuppressWarnings("unchecked")
+ protected T doGetBean(
+ final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
+ throws BeansException {
+
+ final String beanName = transformedBeanName(name);
+ Object bean;
+
+ // Eagerly check singleton cache for manually registered singletons.
+ // a.检查是否已经创建过
+ Object sharedInstance = getSingleton(beanName);
+ // 如果传入的 args 不是 null,那么他肯定是想创建 bean,而不是 获取bean
+ if (sharedInstance != null && args == null) {
+ if (logger.isDebugEnabled()) {
+ if (isSingletonCurrentlyInCreation(beanName)) {
+ logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
+ "' that is not fully initialized yet - a consequence of a circular reference");
+ }
+ else {
+ logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
+ }
+ }
+ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
+ }
+
+ else {
+ // Fail if we're already creating this bean instance:
+ // We're assumably within a circular reference.
+ // 如果我们已经在创建此bean实例,则失败:大概在循环引用中。
+ if (isPrototypeCurrentlyInCreation(beanName)) {
+ throw new BeanCurrentlyInCreationException(beanName);
+ }
+
+ // Check if bean definition exists in this factory.
+ // 检查这个 bean 是否存在 这个 factory
+ BeanFactory parentBeanFactory = getParentBeanFactory();
+ if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
+ // Not found -> check parent.
+ // 没有 去 父工厂 找找
+ String nameToLookup = originalBeanName(name);
+ if (args != null) {
+ // Delegation to parent with explicit args.
+ return (T) parentBeanFactory.getBean(nameToLookup, args);
+ }
+ else {
+ // No args -> delegate to standard getBean method.
+ return parentBeanFactory.getBean(nameToLookup, requiredType);
+ }
+ }
+
+ if (!typeCheckOnly) {
+ // typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
+ markBeanAsCreated(beanName);
+ }
+
+ try {
+ final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
+ checkMergedBeanDefinition(mbd, beanName, args);
+
+ // Guarantee initialization of beans that the current bean depends on.
+ // 确保 初始化的 这些 bean 所依赖的那些 bean 已经初始化成功。
+ // 这里 依赖 是指 我们 配置中显式 depend-on 指定的 bean,
+ // 如果细看之前的步骤,那么对这个应该不陌生,之前有提到过
+ String[] dependsOn = mbd.getDependsOn();
+ if (dependsOn != null) {
+ for (String dep : dependsOn) {
+ if (isDependent(beanName, dep)) {
+ throw new BeanCreationException(mbd.getResourceDescription(), beanName,
+ "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
+ }
+ registerDependentBean(dep, beanName);
+ getBean(dep);
+ }
+ }
+
+ // Create bean instance.
+ // 创建 bean实例
+ if (mbd.isSingleton()) {
+ sharedInstance = getSingleton(beanName, new ObjectFactory() {
+ @Override
+ public Object getObject() throws BeansException {
+ try {
+ return createBean(beanName, mbd, args);
+ }
+ catch (BeansException ex) {
+ // Explicitly remove instance from singleton cache: It might have been put there
+ // eagerly by the creation process, to allow for circular reference resolution.
+ // Also remove any beans that received a temporary reference to the bean.
+ destroySingleton(beanName);
+ throw ex;
+ }
+ }
+ });
+ bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
+ }
+
+ else if (mbd.isPrototype()) {
+ // It's a prototype -> create a new instance.
+ Object prototypeInstance = null;
+ try {
+ beforePrototypeCreation(beanName);
+ prototypeInstance = createBean(beanName, mbd, args);
+ }
+ finally {
+ afterPrototypeCreation(beanName);
+ }
+ bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
+ }
+
+ else {
+ String scopeName = mbd.getScope();
+ final Scope scope = this.scopes.get(scopeName);
+ if (scope == null) {
+ throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
+ }
+ try {
+ Object scopedInstance = scope.get(beanName, new ObjectFactory() {
+ @Override
+ public Object getObject() throws BeansException {
+ beforePrototypeCreation(beanName);
+ try {
+ return createBean(beanName, mbd, args);
+ }
+ finally {
+ afterPrototypeCreation(beanName);
+ }
+ }
+ });
+ bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
+ }
+ catch (IllegalStateException ex) {
+ throw new BeanCreationException(beanName,
+ "Scope '" + scopeName + "' is not active for the current thread; consider " +
+ "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
+ ex);
+ }
+ }
+ }
+ catch (BeansException ex) {
+ cleanupAfterBeanCreationFailure(beanName);
+ throw ex;
+ }
+ }
+
+ // Check if required type matches the type of the actual bean instance.
+ if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
+ try {
+ return getTypeConverter().convertIfNecessary(bean, requiredType);
+ }
+ catch (TypeMismatchException ex) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Failed to convert bean '" + name + "' to required type '" +
+ ClassUtils.getQualifiedName(requiredType) + "'", ex);
+ }
+ throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
+ }
+ }
+ return (T) bean;
+ }
+
+```
+
+```java
+/**
+ * Central method of this class: creates a bean instance,
+ * populates the bean instance, applies post-processors, etc.
+ * @see #doCreateBean
+ */
+@Override
+protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Creating instance of bean '" + beanName + "'");
+ }
+ RootBeanDefinition mbdToUse = mbd;
+
+ // Make sure bean class is actually resolved at this point, and
+ // clone the bean definition in case of a dynamically resolved Class
+ // which cannot be stored in the shared merged bean definition.
+ Class> resolvedClass = resolveBeanClass(mbd, beanName);
+ if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
+ mbdToUse = new RootBeanDefinition(mbd);
+ mbdToUse.setBeanClass(resolvedClass);
+ }
+
+ // Prepare method overrides.
+ try {
+ mbdToUse.prepareMethodOverrides();
+ }
+ catch (BeanDefinitionValidationException ex) {
+ throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
+ beanName, "Validation of method overrides failed", ex);
+ }
+
+ try {
+ // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
+ // 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,
+ Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
+ if (bean != null) {
+ return bean;
+ }
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
+ "BeanPostProcessor before instantiation of bean failed", ex);
+ }
+
+ Object beanInstance = doCreateBean(beanName, mbdToUse, args);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Finished creating instance of bean '" + beanName + "'");
+ }
+ return beanInstance;
+}
+```
+
+### 真正生成Bean实例
+
+```java
+/**
+ * Actually create the specified bean. Pre-creation processing has already happened
+ * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
+ * Differentiates between default bean instantiation, use of a
+ * factory method, and autowiring a constructor.
+ * @param beanName the name of the bean
+ * @param mbd the merged bean definition for the bean
+ * @param args explicit arguments to use for constructor or factory method invocation
+ * @return a new instance of the bean
+ * @throws BeanCreationException if the bean could not be created
+ * @see #instantiateBean
+ * @see #instantiateUsingFactoryMethod
+ * @see #autowireConstructor
+ */
+protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
+ throws BeanCreationException {
+
+ // Instantiate the bean.
+ BeanWrapper instanceWrapper = null;
+ if (mbd.isSingleton()) {
+ instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
+ }
+ // 说明不是 FactoryBean
+ if (instanceWrapper == null) {
+ instanceWrapper = createBeanInstance(beanName, mbd, args);
+ }
+ final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
+ Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
+ mbd.resolvedTargetType = beanType;
+
+ // Allow post-processors to modify the merged bean definition.
+ synchronized (mbd.postProcessingLock) {
+ if (!mbd.postProcessed) {
+ try {
+ applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(mbd.getResourceDescription(), beanName,
+ "Post-processing of merged bean definition failed", ex);
+ }
+ mbd.postProcessed = true;
+ }
+ }
+
+ // Eagerly cache singletons to be able to resolve circular references
+ // even when triggered by lifecycle interfaces like BeanFactoryAware.
+ // 为了解决循环依赖问题
+ boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
+ isSingletonCurrentlyInCreation(beanName));
+ if (earlySingletonExposure) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Eagerly caching bean '" + beanName +
+ "' to allow for resolving potential circular references");
+ }
+ addSingletonFactory(beanName, new ObjectFactory() {
+ @Override
+ public Object getObject() throws BeansException {
+ return getEarlyBeanReference(beanName, mbd, bean);
+ }
+ });
+ }
+
+ // Initialize the bean instance.
+ Object exposedObject = bean;
+ try {
+ // 为实例 设值
+ populateBean(beanName, mbd, instanceWrapper);
+ if (exposedObject != null) {
+ exposedObject = initializeBean(beanName, exposedObject, mbd);
+ }
+ }
+ catch (Throwable ex) {
+ if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
+ throw (BeanCreationException) ex;
+ }
+ else {
+ throw new BeanCreationException(
+ mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
+ }
+ }
+
+ if (earlySingletonExposure) {
+ Object earlySingletonReference = getSingleton(beanName, false);
+ if (earlySingletonReference != null) {
+ if (exposedObject == bean) {
+ exposedObject = earlySingletonReference;
+ }
+ else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
+ String[] dependentBeans = getDependentBeans(beanName);
+ Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
+ for (String dependentBean : dependentBeans) {
+ if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
+ actualDependentBeans.add(dependentBean);
+ }
+ }
+ if (!actualDependentBeans.isEmpty()) {
+ throw new BeanCurrentlyInCreationException(beanName,
+ "Bean with name '" + beanName + "' has been injected into other beans [" +
+ StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
+ "] in its raw version as part of a circular reference, but has eventually been " +
+ "wrapped. This means that said other beans do not use the final version of the " +
+ "bean. This is often the result of over-eager type matching - consider using " +
+ "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
+ }
+ }
+ }
+ }
+
+ // Register bean as disposable.
+ try {
+ registerDisposableBeanIfNecessary(beanName, bean, mbd);
+ }
+ catch (BeanDefinitionValidationException ex) {
+ throw new BeanCreationException(
+ mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
+ }
+
+ return exposedObject;
+}
+```
+
+```java
+/**
+ * Create a new instance for the specified bean, using an appropriate instantiation strategy:
+ * factory method, constructor autowiring, or simple instantiation.
+ * @param beanName the name of the bean
+ * @param mbd the bean definition for the bean
+ * @param args explicit arguments to use for constructor or factory method invocation
+ * @return BeanWrapper for the new instance
+ * @see #instantiateUsingFactoryMethod
+ * @see #autowireConstructor
+ * @see #instantiateBean
+ */
+// 根据 不同的策略生成 bean 如通常 构造器注入 等等
+protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
+ // Make sure bean class is actually resolved at this point.
+ Class> beanClass = resolveBeanClass(mbd, beanName);
+
+ if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
+ throw new BeanCreationException(mbd.getResourceDescription(), beanName,
+ "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
+ }
+
+ if (mbd.getFactoryMethodName() != null) {
+ return instantiateUsingFactoryMethod(beanName, mbd, args);
+ }
+
+ // Shortcut when re-creating the same bean...
+ boolean resolved = false;
+ boolean autowireNecessary = false;
+ if (args == null) {
+ synchronized (mbd.constructorArgumentLock) {
+ if (mbd.resolvedConstructorOrFactoryMethod != null) {
+ resolved = true;
+ autowireNecessary = mbd.constructorArgumentsResolved;
+ }
+ }
+ }
+ if (resolved) {
+ // 构造器注入
+ if (autowireNecessary) {
+ return autowireConstructor(beanName, mbd, null, null);
+ }
+ else {
+ // 构造函数依赖注入
+ return instantiateBean(beanName, mbd);
+ }
+ }
+
+ // Need to determine the constructor...
+ Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
+ if (ctors != null ||
+ mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
+ mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
+ return autowireConstructor(beanName, mbd, ctors, args);
+ }
+
+ // No special handling: simply use no-arg constructor.
+ // 无参构造函数注入
+ return instantiateBean(beanName, mbd);
+}
+```
+
+```java
+/**
+ * Instantiate the given bean using its default constructor.
+ * @param beanName the name of the bean
+ * @param mbd the bean definition for the bean
+ * @return BeanWrapper for the new instance
+ */
+ protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
+ try {
+ Object beanInstance;
+ final BeanFactory parent = this;
+ if (System.getSecurityManager() != null) {
+ beanInstance = AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
+ public Object run() {
+ return getInstantiationStrategy().instantiate(mbd, beanName, parent);
+ }
+ }, getAccessControlContext());
+ }
+ else {
+ beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
+ }
+ BeanWrapper bw = new BeanWrapperImpl(beanInstance);
+ initBeanWrapper(bw);
+ return bw;
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(
+ mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
+ }
+ }
+```
+
+```java
+@Override
+public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
+ // Don't override the class with CGLIB if no overrides.
+ // 如果没有 重写 不要使用 CGLib
+ if (bd.getMethodOverrides().isEmpty()) {
+ Constructor> constructorToUse;
+ synchronized (bd.constructorArgumentLock) {
+ constructorToUse = (Constructor>) bd.resolvedConstructorOrFactoryMethod;
+ if (constructorToUse == null) {
+ final Class> clazz = bd.getBeanClass();
+ if (clazz.isInterface()) {
+ throw new BeanInstantiationException(clazz, "Specified class is an interface");
+ }
+ try {
+ if (System.getSecurityManager() != null) {
+ constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction>() {
+ @Override
+ public Constructor> run() throws Exception {
+ return clazz.getDeclaredConstructor((Class[]) null);
+ }
+ });
+ }
+ else {
+ constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
+ }
+ bd.resolvedConstructorOrFactoryMethod = constructorToUse;
+ }
+ catch (Throwable ex) {
+ throw new BeanInstantiationException(clazz, "No default constructor found", ex);
+ }
+ }
+ }
+ // 使用构造函数实例化
+ return BeanUtils.instantiateClass(constructorToUse);
+ }
+ else {
+ // Must generate CGLIB subclass.
+ return instantiateWithMethodInjection(bd, beanName, owner);
+ }
+}
+```
+
+### 设值
+
+```java
+/**
+ * Populate the bean instance in the given BeanWrapper with the property values
+ * from the bean definition.
+ * @param beanName the name of the bean
+ * @param mbd the bean definition for the bean
+ * @param bw BeanWrapper with bean instance
+ */
+// 给实例 设值
+protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
+ PropertyValues pvs = mbd.getPropertyValues();
+
+ if (bw == null) {
+ if (!pvs.isEmpty()) {
+ throw new BeanCreationException(
+ mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
+ }
+ else {
+ // Skip property population phase for null instance.
+ return;
+ }
+ }
+
+ // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
+ // state of the bean before properties are set. This can be used, for example,
+ // to support styles of field injection.
+ // 到这步的时候,bean 实例化完成(通过工厂方法或构造方法),但是还没开始属性设值,
+ // InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改,
+ boolean continueWithPropertyPopulation = true;
+
+ if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
+ for (BeanPostProcessor bp : getBeanPostProcessors()) {
+ if (bp instanceof InstantiationAwareBeanPostProcessor) {
+ InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
+ if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
+ continueWithPropertyPopulation = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!continueWithPropertyPopulation) {
+ return;
+ }
+
+ if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
+ mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
+ MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
+
+ // Add property values based on autowire by name if applicable.
+ if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
+ autowireByName(beanName, mbd, bw, newPvs);
+ }
+
+ // Add property values based on autowire by type if applicable.
+ if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
+ autowireByType(beanName, mbd, bw, newPvs);
+ }
+
+ pvs = newPvs;
+ }
+
+ boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
+ boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
+
+ if (hasInstAwareBpps || needsDepCheck) {
+ PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
+ if (hasInstAwareBpps) {
+ for (BeanPostProcessor bp : getBeanPostProcessors()) {
+ if (bp instanceof InstantiationAwareBeanPostProcessor) {
+ InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
+ pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
+ if (pvs == null) {
+ return;
+ }
+ }
+ }
+ }
+ if (needsDepCheck) {
+ checkDependencies(beanName, mbd, filteredPds, pvs);
+ }
+ }
+
+ applyPropertyValues(beanName, mbd, bw, pvs);
+}
+```
+
+### initializeBean
+
+```java
+I/**
+ * Initialize the given bean instance, applying factory callbacks
+ * as well as init methods and bean post processors.
+ * Called from {@link #createBean} for traditionally defined beans,
+ * and from {@link #initializeBean} for existing bean instances.
+ * @param beanName the bean name in the factory (for debugging purposes)
+ * @param bean the new bean instance we may need to initialize
+ * @param mbd the bean definition that the bean was created with
+ * (can also be {@code null}, if given an existing bean instance)
+ * @return the initialized bean instance (potentially wrapped)
+ * @see BeanNameAware
+ * @see BeanClassLoaderAware
+ * @see BeanFactoryAware
+ * @see #applyBeanPostProcessorsBeforeInitialization
+ * @see #invokeInitMethods
+ * @see #applyBeanPostProcessorsAfterInitialization
+ */
+protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
+ public Object run() {
+ invokeAwareMethods(beanName, bean);
+ return null;
+ }
+ }, getAccessControlContext());
+ }
+ else {
+ // 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
+ invokeAwareMethods(beanName, bean);
+ }
+
+ Object wrappedBean = bean;
+ if (mbd == null || !mbd.isSynthetic()) {
+ wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
+ }
+
+ try {
+ // 处理 bean 中定义的 init-method,
+ // 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
+ invokeInitMethods(beanName, wrappedBean, mbd);
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(
+ (mbd != null ? mbd.getResourceDescription() : null),
+ beanName, "Invocation of init method failed", ex);
+ }
+
+ if (mbd == null || !mbd.isSynthetic()) {
+ wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
+ }
+ return wrappedBean;
+}
+```
\ No newline at end of file