diff --git a/README.md b/README.md
index 89432b9..a02d168 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,6 @@
| 🍏 | 🍎 | 🍐 | 🍈 | 🥑 | 🥔| 🍠 | 🥝 | 🍱 | 🥞 |🌽| 🥦
| :--------: | :---------: | :---------: | :---------: | :---------: | :---------:| :---------: | :-------: | :-------:| :------:|:------:| :--------: |
| [JAVA基础](#JAVA基础) | [JVM知识](#JVM知识)|[开源框架知识](#开源框架知识) | [操作系统知识](#操作系统) |[多线程与并发](#多线程与并发)|[TCP与HTTP](#TCP与HTTP)| [架构设计与分布式](#架构设计与分布式) |[数据结构与算法](#数据结构与算法)|[数据库](#数据库知识)| [消息队列](#消息队列)|[缓存](#缓存) | [搜索](#搜索)
-### 求职、技术交流微信群
-
### JAVA基础
- [String,Stringbuffer,StringBuilder的区](http://www.cnblogs.com/su-feng/p/6659064.html)。
diff --git a/pom.xml b/pom.xml
index 4594050..5496700 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,12 +20,46 @@
cglib
2.2.2
-
+
+
+
+ org.testng
+ testng
+ 6.14.3
+
+
+
- org.apache.zookeeper
- zookeeper
- 3.4.6
+ com.google.guava
+ guava
+ 23.0
+
+
+ commons-io
+ commons-io
+ 2.4
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.8
+ provided
+
+
+
+ joda-time
+ joda-time
+ 2.10.1
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.9
+
+
diff --git a/src/main/java/com/algorithm/study/demo/LRUCache/LRUCache.java b/src/main/java/com/algorithm/study/demo/LRUCache/LRUCache.java
index 6234068..0fcbb70 100644
--- a/src/main/java/com/algorithm/study/demo/LRUCache/LRUCache.java
+++ b/src/main/java/com/algorithm/study/demo/LRUCache/LRUCache.java
@@ -1,48 +1,152 @@
package com.algorithm.study.demo.LRUCache;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
/**
- * LinkedHashMap实现LRU缓存
+ * LRU缓存链表实现思路
+ * 每次写入数据时将数据放入链表头结点。
+ * 使用数据时候将数据移动到头结点。
+ * 缓存数量超过阈值时移除链表尾部数据。
* @Author: liuxun
- * @CreateDate: 2019/2/13 上午10:24
+ * @CreateDate: 2018/7/12 下午6:05
* @Version: 1.0
*/
public class LRUCache {
- MapCache cache;
- public LRUCache(int capacity) {
- this.cache = new MapCache(capacity);
+ class Node{
+ private int key;
+ private int value;
+ private Node prev;
+ private Node next;
+
+ public Node(int key,int value){
+ this.key=key;
+ this.value=value;
+ }
+ public Node(){}
+
+ public int getKey() {
+ return key;
+ }
+
+ public void setKey(int key) {
+ this.key = key;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+ }
+ private void moveToHead(Node node){
+ remove(node);
+ addNode(node);
}
+ //删除尾节点
+ private Node popTail(){
+ Node prevNode= tail.prev;
+ tail.prev=prevNode.prev;
+ prevNode.prev.next=tail;
- public int get(int key) {
- return cache.getOrDefault(key, -1);
+ prevNode.next=null;
+ prevNode.prev=null;
+
+ size--;
+ return prevNode;
}
+ //删除中间节点
+ private void remove(Node node){
+ Node prevNode=node.prev;
+ Node nextNode=node.next;
- public void put(int key, int value) {
- cache.put(key, value);
+ prevNode.next=nextNode;
+ nextNode.prev=prevNode;
+
+ node.next=null;
+ node.prev=null;
+
+ size--;
}
- public Collection> getAll() {
- return new ArrayList>(cache.entrySet());
+ //添加节点
+ private void addNode(Node node){
+ node.next=head.next;
+ node.prev=head;
+ node.next.prev=node;
+ head.next=node;
+ size++;
+ }
+ private Map cache=new HashMap();
+ private int size=0;
+ private int capacity=0;
+ //头结点
+ private Node head;
+ //尾结点
+ private Node tail;
+ public LRUCache(int capacity) {
+ this.capacity=capacity;
+ //初始化头尾节点
+ this.head=new Node();
+ this.tail=new Node();
+ head.next=tail;
+ tail.prev=head;
}
- class MapCache extends LinkedHashMap {
- public int max;
- public MapCache(int max) {
- super(max, 0.75f, true);
- this.max = max;
+
+ public int get(int key) {
+ //从缓存获取
+ Node node=cache.get(key);
+ if(null==node){
+ return -1;
}
- protected boolean removeEldestEntry(Map.Entry eldest) {
- return size() > max;
+ //数据移到头结点
+ moveToHead(node);
+ return node.value;
+ }
+
+ public void put(int key, int value) {
+ Node node=cache.get(key);
+ if(null==node){
+ node=new Node(key,value);
+ //写入新节点至头节点
+ addNode(node);
+ cache.put(key,node);
+ //如果容量已满,删除尾节点
+ if(size>capacity){
+ //删除尾节点
+ Node delNode=popTail();
+ cache.remove(delNode.key);
+ }
+ }else{
+ //数据更新并移到头结点
+ node.value=value;
+ moveToHead(node);
}
+ }
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder() ;
+ for (Node node = head;node!=null;node=node.next){
+ sb.append(node.getKey()).append(":")
+ .append(node.getValue())
+ .append("-->");
+ }
+ return sb.toString();
}
public static void main(String[] args) {
- LRUCache map = new LRUCache(2) ;
- map.put(1,1);
- System.out.println(map.get(4));
- for (Map.Entry e : map.getAll()){
- System.out.print(e.getKey() + " : " + e.getValue() + "\t");
- }
+ LRUCache lruMap=new LRUCache(2);
+ lruMap.put(1,1);
+ lruMap.put(2,2);
+ lruMap.get(1);
+ lruMap.put(3,3);
+ lruMap.get(2);
+ lruMap.put(4,4);
+ lruMap.get(1);
+ lruMap.get(3);
+ lruMap.get(4);
+ System.out.println(lruMap.toString());
}
-}
-
+}
diff --git a/src/main/java/com/algorithm/study/demo/LRUCache/LRULinkedMap.java b/src/main/java/com/algorithm/study/demo/LRUCache/LRULinkedMap.java
index fab7c86..7f84245 100644
--- a/src/main/java/com/algorithm/study/demo/LRUCache/LRULinkedMap.java
+++ b/src/main/java/com/algorithm/study/demo/LRUCache/LRULinkedMap.java
@@ -25,6 +25,7 @@ public LRULinkedMap(int cacheSize){
* @param eldest
* @return
*/
+ @Override
protected boolean removeEldestEntry(Map.Entry eldest){
return size()>CACHESIZE;
}
diff --git a/src/main/java/com/algorithm/study/demo/LRUCache/LRUMap.java b/src/main/java/com/algorithm/study/demo/LRUCache/LRUMap.java
deleted file mode 100644
index f0363a3..0000000
--- a/src/main/java/com/algorithm/study/demo/LRUCache/LRUMap.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.algorithm.study.demo.LRUCache;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * LRU缓存链表实现思路
- * 每次写入数据时将数据放入链表头结点。
- * 使用数据时候将数据移动到头结点。
- * 缓存数量超过阈值时移除链表尾部数据。
- * @Author: liuxun
- * @CreateDate: 2018/7/12 下午6:05
- * @Version: 1.0
- */
-public class LRUMap {
- private final Map cacheMap = new HashMap<>();
- /**
- * 最大缓存大小
- */
- private int cacheSize;
- /**
- * 节点大小
- */
- private int nodeCount;
- /**
- * 头结点
- */
- private Node header;
- /**
- * 尾结点
- */
- private Node tailer;
- public LRUMap(int cacheSize) {
- this.cacheSize = cacheSize;
- this.header=null;
- this.tailer=null;
- }
- public void put(K key, V value) {
- cacheMap.put(key, value);
- //双向链表中添加结点
- addNode(key, value);
- }
- public V get(K key){
- Node node = getNode(key);
- //移动到头结点
- moveToHead(node) ;
- return cacheMap.get(key);
- }
- private void moveToHead(Node node){
- //如果是最后的一个节点
- if (node.next == null){
- node.tail.next=null;
- tailer=node.tail;
- nodeCount -- ;
- }
- //如果是本来就是头节点 不作处理
- if (node.tail == null){
- return ;
- }
- //如果处于中间节点
- if (node.tail != null && node.next != null){
- //它的上一节点指向它的下一节点 也就删除当前节点
- node.tail.next=node.next;
- nodeCount -- ;
- }
- //最后在头部增加当前节点
- //注意这里需要重新 new 一个对象,不然原本的node 还有着下面的引用,会造成内存溢出。
- node = new Node<>(node.getKey(),node.getValue()) ;
- addHead(node) ;
- }
- /**
- * 链表查询 效率较低
- * @param key
- * @return
- */
- private Node getNode(K key){
- for (Node node = header;node!=null;node=node.next){
- if (node.getKey().equals(key)){
- return node ;
- }
- }
- return null ;
- }
- /**
- * 写入头结点
- * @param key
- * @param value
- */
- private void addNode(K key, V value) {
- Node node = new Node<>(key, value);
- //容量满了删除最后一个
- if (cacheSize == nodeCount) {
- //删除尾结点
- delTail();
- }
- //写入头结点
- addHead(node);
- }
- /**
- * 添加头结点
- *
- * @param node
- */
- private void addHead(Node node) {
- if (header==null){
- tailer=node;
- }else{
- header.tail=node;
- node.next=header;
- }
- header=node;
- nodeCount++;
- }
- private void delTail() {
- //把尾结点从缓存中删除
- cacheMap.remove(tailer.getKey());
- tailer.tail.next=null;
- tailer=tailer.tail;
- nodeCount--;
- }
- private class Node {
- private K key;
- private V value;
- Node tail;
- Node next;
- public Node(K key, V value) {
- this.key = key;
- this.value = value;
- }
- public Node() {
- }
- public K getKey() {
- return key;
- }
- public void setKey(K key) {
- this.key = key;
- }
- public V getValue() {
- return value;
- }
- public void setValue(V value) {
- this.value = value;
- }
- }
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder() ;
- for (Node node = header;node!=null;node=node.next){
- if (node.getKey()!=null){
- sb.append(node.getKey()).append(":")
- .append(node.getValue())
- .append("-->");
- }
- }
- return sb.toString();
- }
- public static void main(String[] args) {
- LRUMap lruMap=new LRUMap<>(3);
- lruMap.put("1","1");
- lruMap.put("2","2");
- lruMap.put("3","3");
- lruMap.get("1");
- lruMap.put("4","4");
- System.out.println(lruMap.toString());
- System.out.println(lruMap.cacheSize);
- }
-
-}
diff --git a/src/main/java/com/algorithm/study/demo/MainTest.java b/src/main/java/com/algorithm/study/demo/MainTest.java
deleted file mode 100644
index 619c3e9..0000000
--- a/src/main/java/com/algorithm/study/demo/MainTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.algorithm.study.demo;
-
-import java.io.*;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-
-/**
- * @Author: liuxun
- * @CreateDate: 2019/1/2 上午11:29
- * @Version: 1.0
- */
-public class MainTest {
- public static void main(String[] args) {
- try {
- String filePath="/Users/liuxun/csv.txt";
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
-
- File file=new File(filePath);
- File out=new File("/Users/liuxun/out.txt");
- createFile(out);
-
- BufferedReader reader=new BufferedReader(new FileReader(file));
- String temp=null;
- while ((temp=reader.readLine())!=null){
- StringBuffer sb=new StringBuffer();
- //双引号内的逗号不分割 双引号外的逗号进行分割
- String[] strArr = temp.trim().split(",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)",-1);
- if (strArr.length<=5){
- System.out.println("数据格式不准确");
- continue;
- }
- sb.append(Integer.valueOf(strArr[0])).append("\t");
- sb.append("'"+strArr[1]+"'").append("\t");
- sb.append("'"+strArr[2]+"'").append("\t");
- sb.append(Float.valueOf(strArr[3])).append("\t").append("\t");
- sb.append(sdf1.format(sdf.parse(strArr[4])));
- System.out.println(sb.toString());
- fileChaseFW("/Users/liuxun/out.txt",sb.toString());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 写入TXT,追加写入
- * @param filePath
- * @param content
- */
- public static void fileChaseFW(String filePath, String content) {
- try {
- //构造函数中的第二个参数true表示以追加形式写文件
- FileWriter fw = new FileWriter(filePath,true);
- fw.write(content+"\n");
- fw.close();
- } catch (Exception e) {
- System.out.println("文件写入失败!" + e);
- }
- }
- /**
- * 创建文件
- * @param fileName
- * @return
- */
- public static boolean createFile(File fileName)throws Exception{
- try{
- if(!fileName.exists()){
- fileName.createNewFile();
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- return true;
- }
-
-
-}
diff --git a/src/main/java/com/algorithm/study/demo/MainTest1.java b/src/main/java/com/algorithm/study/demo/MainTest1.java
new file mode 100644
index 0000000..0c3d776
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/MainTest1.java
@@ -0,0 +1,36 @@
+package com.algorithm.study.demo;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author xun2.liu
+ * @title: MainTest1
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2020/6/24 17:30
+ */
+public class MainTest1 {
+ public static void main(String[] args) {
+ List> lists=new ArrayList<>();
+ if((lists.size() & 1)==1){
+ LinkedList ls=new LinkedList<>();
+ //奇数层放到队列尾部
+ ls.addLast(3);
+ lists.add(ls);
+ }else{
+ LinkedList ls=new LinkedList<>();
+ //偶数层放到队列头部
+ ls.addFirst(9);
+ ls.addFirst(2);
+ lists.add(ls);
+ }
+
+ System.out.println(JSON.toJSONString(lists));
+ System.out.println((2 & 1));
+
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/OptionalTest.java b/src/main/java/com/algorithm/study/demo/OptionalTest.java
new file mode 100644
index 0000000..7081aba
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/OptionalTest.java
@@ -0,0 +1,21 @@
+package com.algorithm.study.demo;
+
+import com.algorithm.study.demo.string.TestString;
+
+import java.math.BigDecimal;
+import java.text.NumberFormat;
+import java.util.Optional;
+
+/**
+ * @title: OptionalTest
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/8/21 10:10
+ */
+public class OptionalTest {
+ public static void main(String[] args) {
+ for (int i = 5; i > 0; i--) {
+ System.out.println(i);
+ }
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/FindProject.java b/src/main/java/com/algorithm/study/demo/algorithm/FindProject.java
index b46445d..90ca547 100644
--- a/src/main/java/com/algorithm/study/demo/algorithm/FindProject.java
+++ b/src/main/java/com/algorithm/study/demo/algorithm/FindProject.java
@@ -1,12 +1,5 @@
package com.algorithm.study.demo.algorithm;
-import com.alibaba.fastjson.JSON;
-import com.sun.deploy.util.StringUtils;
-
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* 查找算法
* Created by liuxun on 2017/4/25.
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/SortProject.java b/src/main/java/com/algorithm/study/demo/algorithm/SortProject.java
index 15348d9..ec90f5d 100644
--- a/src/main/java/com/algorithm/study/demo/algorithm/SortProject.java
+++ b/src/main/java/com/algorithm/study/demo/algorithm/SortProject.java
@@ -61,17 +61,17 @@ public static void performanceTest(int len) throws Exception{
* 时间复杂度为O(n²)
* 空间复杂度为O(1)
*/
- private static void maopaoSort(int score[]){
- System.out.println("排序前:"+ JSON.toJSONString(score));
- boolean flag=true;//数据发生了交换才继续冒泡
- for (int i = 1; i < score.length && flag; i++){ //最多做n-1趟排序
- flag=false;
- for(int j = 0 ;j < score.length - i; j++){ //对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
- if(score[j] > score[j + 1]){ //把大或者小的值交换到后面
- int temp = score[j];
- score[j] = score[j + 1];
- score[j + 1] = temp;
- flag=true;//发生了数据交换
+ private static void maopaoSort(int score[]){
+ System.out.println("排序前:"+ JSON.toJSONString(score));
+ boolean flag=true;//数据发生了交换才继续冒泡
+ for (int i = 1; i < score.length && flag; i++){ //最多做n-1趟排序
+ flag=false;
+ for(int j = 0 ;j < score.length - i; j++){ //对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
+ if(score[j] > score[j + 1]){ //把大或者小的值交换到后面
+ int temp = score[j];
+ score[j] = score[j + 1];
+ score[j + 1] = temp;
+ flag=true;//发生了数据交换
}
}
}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/Suanfa50.java b/src/main/java/com/algorithm/study/demo/algorithm/Suanfa50.java
deleted file mode 100644
index 212720b..0000000
--- a/src/main/java/com/algorithm/study/demo/algorithm/Suanfa50.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.algorithm.study.demo.algorithm;
-
-import java.util.Arrays;
-import java.util.BitSet;
-
-/**
- * @Author: liuxun
- * @CreateDate: 2018/12/7 下午1:35
- * @Version: 1.0
- */
-public class Suanfa50 {
- public static void main(String[] args) {
-// printMissingNumber(new int[]{1, 3, 6}, 6);
- }
- private static void printMissingNumber(int[] numbers, int count) {
- int missingCount = count - numbers.length;
- BitSet bitSet = new BitSet(count);
-
- for (int number : numbers) {
- bitSet.set(number - 1);
- }
-
- System.out.printf("Missing numbers in integer array %s, with total number %d is %n",
- Arrays.toString(numbers), count);
- int lastMissingIndex = 0;
-
- for (int i = 0; i < missingCount; i++) {
- lastMissingIndex = bitSet.nextClearBit(lastMissingIndex);
- System.out.println(++lastMissingIndex);
- }
-
- }
-
-
-}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/dynamicprogramming/demo1.java b/src/main/java/com/algorithm/study/demo/algorithm/dynamicprogramming/demo1.java
new file mode 100644
index 0000000..31b98a5
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/dynamicprogramming/demo1.java
@@ -0,0 +1,88 @@
+package com.algorithm.study.demo.algorithm.dynamicprogramming;
+
+/**
+ * @author xun2.liu
+ * @title: demo1
+ * @projectName algorithm-study
+ * @description: 动态规划-斐波那契数列
+ * @date 2020/3/18 14:04
+ */
+public class demo1 {
+ public static void main(String[] args) {
+ System.out.println(fib(10));
+ System.out.println(fib2(10));
+ System.out.println(fib3(10));
+ System.out.println(fib4(10));
+ }
+
+ /**
+ * 重叠子问题,子问题个数为 O(2^n)。性能非常低。
+ * @param n
+ * @return
+ */
+ private static int fib(int n){
+ if(n==1 || n==2){
+ return 1;
+ }
+ return fib(n-1)+fib(n-2);
+ }
+
+ /**
+ * 带备忘录的递归解法,解决重叠子问题。
+ * 子问题个数为 O(n),时间复杂度是 O(n)
+ * @param n
+ * @return
+ */
+ private static int fib2(int n){
+ if(n==1 || n==2){
+ return 1;
+ }
+ int[] memo=new int[n+1];
+ return helper(memo,n);
+ }
+ private static int helper(int[] memo,int n){
+ if(n==1 || n==2){
+ return 1;
+ }
+ if (memo[n]!=0) {
+ return memo[n];
+ }
+ return memo[n]=helper(memo,n-1)+helper(memo,n-2);
+ }
+
+ /**
+ * DP table 数组的迭代解法
+ * 空间复杂度降为 O(N)
+ *自底向上计算斐波那契数列
+ * @param n
+ * @return
+ */
+ private static int fib3(int n){
+ int[] temp=new int[n+1];
+ temp[1]=temp[2]=1;
+ for (int i=3;i<=n;i++){
+ temp[i]=temp[i-1]+temp[i-2];
+ }
+ return temp[n];
+ }
+
+ /**
+ *DP table 数组的迭代解法优化
+ *空间复杂度降为 O(1)
+ *自底向上计算斐波那契数列
+ * @param n
+ * @return
+ */
+ private static int fib4(int n){
+ if (n==1 || n==2){
+ return 1;
+ }
+ int prev=1;int curr=1;
+ for (int i=3;i<=n;i++){
+ int temp=prev+curr;
+ prev=curr;
+ curr=temp;
+ }
+ return curr;
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/MoneyBusi.java b/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/MoneyBusi.java
new file mode 100644
index 0000000..e402baa
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/MoneyBusi.java
@@ -0,0 +1,25 @@
+package com.algorithm.study.demo.algorithm.greedyalgorithm;
+
+import lombok.*;
+
+/**
+ * @title: MoneyBusi
+ * @projectName algorithm-study
+ * @description: 零钱支付
+ * @date 2019/11/14 17:19
+ */
+@Getter
+@Setter
+@ToString
+@AllArgsConstructor
+@NoArgsConstructor
+public class MoneyBusi {
+ /** 面值 */
+ private String value;
+
+ /** 张数 */
+ private int num;
+
+ /** 金额 */
+ private int memory;
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/Solutions.java b/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/Solutions.java
new file mode 100644
index 0000000..761a235
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/greedyalgorithm/Solutions.java
@@ -0,0 +1,100 @@
+package com.algorithm.study.demo.algorithm.greedyalgorithm;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.PriorityQueue;
+
+/**
+ * @author liuxun
+ * @title: Solutions
+ * @projectName algorithm-study
+ * @description: 零钱支付问题
+ * 假设我们有 1 元、2 元、5 元、10 元、20 元、50 元、100 元这些面额的纸币,
+ * 它们的张数分别是 c1、c2、c5、c10、c20、c50、c100。
+ * 我们现在要用这些钱来支付 K 元,最少要用多少张纸币呢?
+ * 先用面值最大的来支付,如果不够,就继续用更小一点面值的,以此类推,最后剩下的用 1 元来补齐。
+ * @date 2019/11/14 17:20
+ */
+public class Solutions {
+ /**
+ * 用于存储金额的信息,根据金额从大到小排序
+ */
+ public PriorityQueue moneyQueue =
+ new PriorityQueue<>(
+ (o1, o2) -> {
+ if (o1.getMemory() < o2.getMemory()) {
+ return 1;
+ } else if (o1.getMemory() > o2.getMemory()) {
+ return -1;
+ }
+ return 0;
+ });
+
+ /**
+ * 添加金额信息
+ * @param value 面值信息
+ * @param num 张数
+ * @param memory 金额值
+ */
+ public void addMemoryInfo(String value, int num, int memory) {
+ moneyQueue.offer(new MoneyBusi(value, num, memory));
+ }
+
+ /**
+ * 计算找零钱的问题
+ *
+ * @param money 找零的金额信息
+ * @return 找零钱的信息
+ */
+ public List looseChange(int money) {
+
+ List resultMemory = new ArrayList<>();
+
+ List moreMemory = new ArrayList<>();
+
+ int surplus = money;
+
+ while (surplus > 0) {
+ //返回队列头部元素
+ MoneyBusi busi = moneyQueue.peek();
+ if (null != busi) {
+ System.out.println("当前金额:"+busi.getMemory());
+ if (busi.getMemory() <= surplus) {
+ busi = moneyQueue.poll();
+ surplus = surplus - busi.getMemory();
+
+ MoneyBusi busiNew = new MoneyBusi(busi.getValue(), 1, busi.getMemory());
+ resultMemory.add(busiNew);
+
+ busi.setNum(busi.getNum() - 1);
+
+ if (busi.getNum() > 0) {
+ moneyQueue.offer(busi);
+ }
+ } else {
+ moreMemory.add(moneyQueue.poll());
+ }
+ } else {
+ break;
+ }
+ }
+ moneyQueue.addAll(moreMemory);
+ return resultMemory;
+ }
+
+ public static void main(String[] args) {
+ Solutions instance = new Solutions();
+ instance.addMemoryInfo("100元", 2, 100);
+ instance.addMemoryInfo("50元", 2, 50);
+ instance.addMemoryInfo("20元", 2, 20);
+ instance.addMemoryInfo("10元", 2, 10);
+ instance.addMemoryInfo("5元", 2, 5);
+ instance.addMemoryInfo("2元", 2, 2);
+ instance.addMemoryInfo("1元", 5, 1);
+ System.out.println(instance.moneyQueue);
+ List list = instance.looseChange(332);
+ for (MoneyBusi busi : list) {
+ System.out.println(busi);
+ }
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/huffman/DataOutputStreamHuffman.java b/src/main/java/com/algorithm/study/demo/algorithm/huffman/DataOutputStreamHuffman.java
new file mode 100644
index 0000000..1d622e4
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/huffman/DataOutputStreamHuffman.java
@@ -0,0 +1,59 @@
+package com.algorithm.study.demo.algorithm.huffman;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * @author xun2.liu
+ * @title: DataOutputStreamHuffman
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/11/19 17:03
+ */
+public class DataOutputStreamHuffman {
+
+ public static final DataOutputStreamHuffman OUTPUT = new DataOutputStreamHuffman();
+
+ public static final String path = "D:\\java\\test\\datastruct\\hoffman\\";
+
+ public void outtoFile(byte[] value) {
+ FileOutputStream output = null;
+ try {
+ output = new FileOutputStream(path + "src.file");
+ output.write(value);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (null != output) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void outHuffmantoFile(byte[] value) {
+ FileOutputStream output = null;
+ try {
+ output = new FileOutputStream(path + "out.huff");
+ output.write(value);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (null != output) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/huffman/HuffmanCode.java b/src/main/java/com/algorithm/study/demo/algorithm/huffman/HuffmanCode.java
new file mode 100644
index 0000000..6de61a1
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/huffman/HuffmanCode.java
@@ -0,0 +1,193 @@
+package com.algorithm.study.demo.algorithm.huffman;
+
+import java.util.*;
+/**
+ * @author xun2.liu
+ * @title: HuffmanCode
+ * @projectName algorithm-study
+ * @description: Huffman编码
+ * @date 2019/11/19 17:03
+ */
+public class HuffmanCode {
+ /** 根节点信息,根据编码后设置根节点信息 */
+ public CodeNode root;
+
+ /** 节点信息 */
+ public class CodeNode {
+ /** 编码存储的数据信息 */
+ public char data;
+
+ /** 字符出现的频率 */
+ public int frequence;
+
+ /** 霍夫漫编码左节点 */
+ public CodeNode left;
+
+ /** 霍夫漫编码右节点 */
+ public CodeNode right;
+
+ /** 父节点信息 */
+ public CodeNode parent;
+
+ /** 标识是否为计算添加节点 */
+ public boolean addNode;
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("CodeNode{");
+ sb.append("data=").append(data);
+ sb.append(", frequence=").append(frequence);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+ /**
+ * 编码,形成每个字符的霍夫漫编码
+ *
+ * @param map 统计信息
+ * @return 结果编码后的信息
+ */
+ public Map getHuffManCode(Map map) {
+ if (null != map && !map.isEmpty()) {
+ // 使用小顶堆来进行数据的存储
+ PriorityQueue nodePriQueue =
+ new PriorityQueue<>(
+ map.size(),
+ (o1, o2) -> {
+ if (o1.frequence > o2.frequence) {
+ return 1;
+ } else if (o1.frequence < o2.frequence) {
+ return -1;
+ }
+ return 0;
+ });
+
+ CodeNode nodeTmp = null;
+
+ // 1,将数据放入小顶堆中
+ for (Map.Entry item : map.entrySet()) {
+
+ nodeTmp = new CodeNode();
+ nodeTmp.data = item.getKey();
+ nodeTmp.frequence = item.getValue();
+
+ nodePriQueue.offer(nodeTmp);
+ }
+
+ int queueSize = nodePriQueue.size();
+
+ // 将统计数据编译成霍夫漫编码树信息
+ for (int i = 1; i < queueSize; i++) {
+ CodeNode left = nodePriQueue.poll();
+ CodeNode right = nodePriQueue.poll();
+
+ CodeNode sumNode = new CodeNode();
+ sumNode.frequence = left.frequence + right.frequence;
+ sumNode.data = (char) ((int) left.data + (int) right.data);
+ sumNode.addNode = true;
+
+ sumNode.left = left;
+ sumNode.right = right;
+
+ left.parent = sumNode;
+ right.parent = sumNode;
+
+ nodePriQueue.offer(sumNode);
+ }
+
+ // 构建完成
+ root = nodePriQueue.poll();
+
+ // 构建霍夫漫编码
+ Map result = this.builderCode(root);
+
+ return result;
+ }
+
+ return null;
+ }
+
+ public Map builderCode(CodeNode root) {
+
+ Map result = new HashMap<>();
+
+ StringBuilder code = new StringBuilder();
+
+ this.buildCode(code, root, result);
+
+ return result;
+ }
+
+ /**
+ * 进行霍夫温编码的操作,此处使用递归来实现
+ *
+ * @param code 主串信息
+ * @param node 霍夫漫编码树信息
+ * @param result 存储的结果节点信息
+ */
+ private void buildCode(StringBuilder code, CodeNode node, Map result) {
+ if (null == node) {
+ return;
+ }
+
+ if (!node.addNode) {
+ result.put(node.data, code.toString());
+ }
+
+ if (node.left != null) {
+ code.append("0");
+ this.buildCode(code, node.left, result);
+ code.deleteCharAt(code.length() - 1);
+ }
+
+ if (node.right != null) {
+ code.append("1");
+ this.buildCode(code, node.right, result);
+ code.deleteCharAt(code.length() - 1);
+ }
+ }
+
+ public String parseHuffman2(String src, Map huffman) {
+ StringBuilder out = new StringBuilder();
+
+ char[] hufSrcs = src.toCharArray();
+
+ for (char hufs : hufSrcs) {
+ out.append(huffman.get(hufs));
+ }
+
+ return out.toString();
+ }
+
+ /**
+ * 进行霍夫漫的解码操作
+ *
+ * @param hufStr
+ * @param root
+ * @return
+ */
+ public String decodeHuffman(String hufStr, CodeNode root) {
+ char[] hubs = hufStr.toCharArray();
+
+ int index = 0;
+
+ StringBuilder resultMsg = new StringBuilder();
+
+ while (index < hubs.length) {
+ CodeNode node = root;
+
+ do {
+ if (hubs[index] == '0') {
+ node = node.left;
+ } else if (hubs[index] == '1') {
+ node = node.right;
+ }
+ index++;
+ } while (index < hubs.length && (node.left != null || node.right != null));
+
+ resultMsg.append(node.data);
+ }
+
+ return resultMsg.toString();
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/huffman/StrProc.java b/src/main/java/com/algorithm/study/demo/algorithm/huffman/StrProc.java
new file mode 100644
index 0000000..cf753bd
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/huffman/StrProc.java
@@ -0,0 +1,42 @@
+package com.algorithm.study.demo.algorithm.huffman;
+
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * @author xun2.liu
+ * @title: StrProc
+ * @projectName algorithm-study
+ * @description: 对字符进行统计
+ * @date 2019/11/19 17:07
+ */
+public class StrProc {
+ /**
+ * 对字符进行统计操作
+ *
+ * @param str
+ * @return
+ */
+ public static Map countCharset(String str) {
+
+ if (null != str && str.length() > 0) {
+
+ Map result = new HashMap<>();
+
+ char[] strChars = str.toCharArray();
+
+ Integer value = null;
+ for (int i = 0; i < strChars.length; i++) {
+ value = result.get(strChars[i]);
+
+ if (value == null) {
+ result.put(strChars[i], 1);
+ } else {
+ result.put(strChars[i], value + 1);
+ }
+ }
+
+ return result;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/huffman/TestHuffmanCode.java b/src/main/java/com/algorithm/study/demo/algorithm/huffman/TestHuffmanCode.java
new file mode 100644
index 0000000..af4f299
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/huffman/TestHuffmanCode.java
@@ -0,0 +1,41 @@
+package com.algorithm.study.demo.algorithm.huffman;
+
+
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+/**
+ * @author xun2.liu
+ * @title: TestHuffmanCode
+ * @projectName algorithm-study
+ * @description: huffman编码测试
+ * @date 2019/11/19 17:08
+ */
+public class TestHuffmanCode {
+ public static void main(String[] args) {
+// for (int i = 0; i < 5; i++) {
+ int valueRand = ThreadLocalRandom.current().nextInt(1, 50);
+ StringBuilder msg = new StringBuilder();
+ for (int j = 0; j < valueRand; j++) {
+ msg.append((char) ThreadLocalRandom.current().nextInt(65, 122));
+ }
+
+ String src = "aaaaaaabbcceed" + msg.toString();
+ System.out.println("原始:" + src);
+
+ Map conMap = StrProc.countCharset(src);
+
+ System.out.println("字符频率统计:"+conMap);
+
+ HuffmanCode instance = new HuffmanCode();
+ Map huffCode = instance.getHuffManCode(conMap);
+ System.out.println("huffcode字符编码映射:"+huffCode);
+
+ String hufOutValue = instance.parseHuffman2(src, huffCode);
+ System.out.println("最终编码:"+hufOutValue);
+
+ String deValue = instance.decodeHuffman(hufOutValue, instance.root);
+ System.out.println("解压结果:" + deValue);
+
+ System.out.println("--------------------------------------------------------------------------------");
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution.java
new file mode 100644
index 0000000..97af0e9
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution.java
@@ -0,0 +1,78 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+import com.algorithm.study.demo.LRUCache.LRUCache;
+
+/**
+ * @author xun2.liu
+ * @title: Solution
+ * @projectName algorithm-study
+ * @description:
+ * 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,
+ * 并且它们的每个节点只能存储 一位 数字。
+ *
+ * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
+ *
+ * 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
+ * 示例:
+ *
+ * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
+ * 输出:7 -> 0 -> 8
+ * 原因:342 + 465 = 807
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/add-two-numbers
+ * @date 2020/5/9 14:42
+ */
+public class Solution {
+ static class ListNode{
+ private int val;
+ private ListNode next;
+ private ListNode(int val){
+ this.val=val;
+ }
+
+ }
+
+ public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
+ //返回的结果,初始化
+ ListNode result=new ListNode(0);
+ //j结果游标
+ ListNode curr=result;
+ //满十进1,存储进位
+ int carry=0;
+ while(l1!=null || l2!=null){
+ int p1=l1==null?0:l1.val;
+ int p2=l2==null?0:l2.val;
+ //计算当前两数相加后的值
+ int sum=p1+p2+carry;
+ //计算相加后的值的进位
+ carry=sum/10;
+ //存储当前相加后的值除以10的余数
+ curr.next=new ListNode(sum%10);
+ //游标指向下个节点
+ curr=curr.next;
+
+ if (l1!=null){
+ l1=l1.next;
+ }
+ if (l2!=null){
+ l2=l2.next;
+ }
+ }
+ if (carry>0){
+ curr.next=new ListNode(carry);
+ }
+ return result.next;
+ }
+ public static void main(String[] args) {
+ ListNode a=new ListNode(5);
+ ListNode b=new ListNode(5);
+ a.next=b;
+
+
+ ListNode result = addTwoNumbers(a, a);
+ for (ListNode node=result;node!=null;node=node.next){
+ System.out.println(node.val);
+ }
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution10.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution10.java
new file mode 100644
index 0000000..21e3809
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution10.java
@@ -0,0 +1,58 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author xun2.liu
+ * @title: Solution10
+ * @projectName algorithm-study
+ * @description: 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
+ *
+ * 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
+ *
+ * 示例 1:
+ *
+ * 输入: "abc"
+ * 输出: 3
+ * 解释: 三个回文子串: "a", "b", "c".
+ * 示例 2:
+ *
+ * 输入: "aaa"
+ * 输出: 6
+ * 说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/palindromic-substrings
+ * @date 2020/5/21 15:34
+ */
+public class Solution10 {
+ //通过中心扩散法查找回文字符串
+ public static void huiwen(String s,int l,int r,List filter){
+ while(l>=0 && r filter=new ArrayList();
+ for(int i=0;ilen){
+ return -1;
+ }
+ if (len==n && haystack.equals(needle)){
+ return 0;
+ }
+ for (int i=0;i2->4, 1->3->4
+ * 输出:1->1->2->3->4->4
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/merge-two-sorted-lists
+ */
+public class Solution14 {
+ public static class ListNode {
+ int val;
+ ListNode next;
+ ListNode(int x) { val = x; }
+ }
+ public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
+ //需要返回排序好的节点
+ ListNode result=new ListNode(-1);
+ //哨兵节点
+ ListNode prev=result;
+ //首先遍历两个链表比较大小如果l1比l2小。l1往前走否则l2往前走。并且把值小的节点赋值给prev.next。
+ while(l1!=null && l2!=null){
+ if(l1.val map= new HashMap<>();
+ for(int i=0;i queue=new LinkedList<>();
+ //把当前的第一层添加至队列中
+ queue.offer(root);
+ //默认深度为0
+ int depth=0;
+ while (queue.size()>0){
+ //获取当前层的节点数量
+ int size = queue.size();
+ //遍历当前层的节点
+ for (int i = 0; i < size; i++) {
+ //弹出当前层的节点。获取节点下一层的节点
+ TreeNode head = queue.poll();
+ if (head.left!=null){
+ queue.offer(head.left);
+ }
+ if (head.right!=null){
+ queue.offer(head.right);
+ }
+ }
+ //当前层遍历结束后。树的深度+1
+ depth++;
+ }
+ return depth;
+
+ }
+ public static void main(String[] args) {
+ TreeNode a=new TreeNode(3);
+ TreeNode b=new TreeNode(9);
+ TreeNode c=new TreeNode(20);
+ TreeNode d=new TreeNode(15);
+ TreeNode r=new TreeNode(7);
+ a.left=b;
+ a.right=c;
+ c.left=d;
+ c.right=r;
+ System.out.println(maxDepth(a));
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution19.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution19.java
new file mode 100644
index 0000000..df36d40
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution19.java
@@ -0,0 +1,79 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * @author xun2.liu
+ * @title: Solution19
+ * @projectName algorithm-study
+ * @description: 给定一个二叉树,返回它的中序 遍历。
+ *
+ * 示例:
+ *
+ * 输入: [1,null,2,3]
+ * 1
+ * \
+ * 2
+ * /
+ * 3
+ *
+ * 输出: [1,3,2]
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal
+ * @date 2020/5/29 18:31
+ */
+public class Solution19 {
+ public static class TreeNode {
+ int val;
+ TreeNode left;
+ TreeNode right;
+ TreeNode(int x) { val = x; }
+ }
+
+ /**
+ * 前序遍历:打印-左-右
+ * 中序遍历:左-打印-右
+ * 后序遍历:左-右-打印
+ * @param root
+ * @return
+ */
+ public static List inorderTraversal(TreeNode root) {
+ List result=new ArrayList();
+ Stack stack=new Stack();
+ TreeNode curr=root;
+ while(curr!=null || !stack.isEmpty()){
+ //首先遍历左子节点
+ if (curr!=null){
+ //不断往左子树方向走,每走一次就将当前节点保存到栈中
+ //这是模拟递归的调用
+ stack.push(curr);
+ curr=curr.left;
+ }else{
+ //当前节点为空,说明左边走到头了,从栈中弹出节点并保存
+ //然后转向右边节点,继续上面整个过程
+ curr= stack.pop();
+ result.add(curr.val);
+ curr=curr.right;
+ }
+ }
+ return result;
+ }
+ public static void main(String[] args) {
+ TreeNode a=new TreeNode(3);
+ TreeNode b=new TreeNode(9);
+ TreeNode c=new TreeNode(20);
+ TreeNode d=new TreeNode(15);
+ TreeNode r=new TreeNode(2);
+ a.left=b;
+ a.right=c;
+ c.left=d;
+ c.right=r;
+ List integers = inorderTraversal(a);
+ for (Integer integer : integers) {
+ System.out.println(integer);
+ }
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution2.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution2.java
new file mode 100644
index 0000000..5eae01b
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution2.java
@@ -0,0 +1,58 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author xun2.liu
+ * @title: Solution2
+ * @projectName algorithm-study
+ * @description:
+ * 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
+ * 示例 1:
+ *
+ * 输入: "abcabcbb"
+ * 输出: 3
+ * 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
+ * @date 2020/5/13 15:51
+ */
+public class Solution2 {
+ /**
+ * 使用滑动窗口
+ * 定义一个 map 数据结构存储 (k, v),其中 key 值为字符,value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重复
+ * 我们定义不重复子串的开始位置为 start,结束位置为 end
+ * 随着 end 不断遍历向后,会遇到与 [start, end] 区间内字符相同的情况,此时将字符作为 key 值,获取其 value 值,并更新 start,此时 [start, end]
+ * 区间内不存在重复字符
+ * 无论是否更新 start,都会更新其 map 数据结构和结果 ans。
+ * 时间复杂度:O(n)O(n)
+ * @param s
+ * @return
+ */
+ public static int lengthOfLongestSubstring(String s) {
+ //最长子串 的长度
+ int resultLen=0;
+ //key为字符 value为end
+ Map map= new HashMap<>();
+ //初始化起始位置和结束位置
+ int start=0;
+ for(int end=0;end='0' && str.charAt(i)<='9') {
+ //'0'的ASCII码是48,'1'的是49,这么一减就从就可以得到真正的整数值
+ int tmp = str.charAt(i)-48;
+ //判断是否大于 最大32位整数
+ if(!is_negative &&(res>Integer.MAX_VALUE ||(res==Integer.MAX_VALUE && tmp>=7))) {
+ return Integer.MAX_VALUE;
+ }
+ //判断是否小于 最小32位整数
+ if(is_negative &&(-res<-Integer.MAX_VALUE || (-res==-Integer.MAX_VALUE && tmp>=8))) {
+ return -Integer.MAX_VALUE;
+ }
+ res = res*10 + tmp;
+ ++i;
+ }
+ //如果有负号标记则返回负数
+ if(is_negative) {
+ return -res;
+ }
+ return res;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(myAtoi("-42"));
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution22.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution22.java
new file mode 100644
index 0000000..836babf
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution22.java
@@ -0,0 +1,46 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+/**
+ * @author xun2.liu
+ * @title: Solution22
+ * @projectName algorithm-study
+ * @description: 字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。
+ * 比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。
+ * 你可以假设字符串中只包含大小写英文字母(a至z)。
+ * 示例1:
+ *
+ * 输入:"aabcccccaaa"
+ * 输出:"a2b1c5a3"
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/compress-string-lcci
+ * @date 2020/6/3 20:07
+ */
+public class Solution22 {
+ public static String compressString(String S) {
+ //慢指针
+ int i=0;
+ int len=S.length();
+ //压缩后的字符串
+ StringBuilder sb=new StringBuilder();
+ while(i counter=new HashMap<>();
+ for(int n:nums){
+ counter.put(n,counter.getOrDefault(n,0)+1);
+ }
+ //使用每个数字出现的次数作为排序规则来建立初始化一个优先队列
+ PriorityQueue heap=new PriorityQueue<>((n1,n2)-> counter.get(n1)-counter.get(n2));
+ //把数字写入优先队列中
+ for(int num:counter.keySet()){
+ heap.add(num);
+ //如果优先队列中的元素大于前K个就删除,因为默认是升序。
+ if(heap.size()>k){
+ heap.poll();
+ }
+ }
+ //取出前K个元素从优先队列中
+ int[] result=new int[k];
+ for(int i=0;i> temp=new ArrayList<>();
+ int value=0;
+ int remainder=0;
+ boolean flag=false;
+ while (!flag){
+ value=a / b;
+ remainder= a%b;
+ for (int i=0;i integerIntegerMap = temp.get(i);
+ //如果相除得到的整数答案和余数在之前出现过,那么就会开始循环。也就是循环节点
+ if (integerIntegerMap.containsKey(value) && integerIntegerMap.containsValue(remainder)){
+ flag=true;
+ break;
+ }
+ }
+ HashMap map = new HashMap<>();
+ map.put(value,remainder);
+ temp.add(map);
+ a=remainder*10;
+ }
+ StringBuilder sb=new StringBuilder();
+ for (int i=1;i integerIntegerMap = temp.get(i);
+ integerIntegerMap.forEach((k,v)->{
+ sb.append(k);
+ });
+
+ }
+ return sb.toString();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(function(3,7));
+ }
+
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution5.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution5.java
new file mode 100644
index 0000000..39e6f26
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution5.java
@@ -0,0 +1,43 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+/**
+ * @author xun2.liu
+ * @title: Solution5
+ * @projectName algorithm-study
+ * @description: 反转一个单链表。
+ * 示例:
+ * 输入: 1->2->3->4->5->NULL
+ * 输出: 5->4->3->2->1->NULL
+ * @date 2020/5/14 20:07
+ */
+public class Solution5 {
+ public static class ListNode {
+ int val;
+ ListNode next;
+ ListNode(int x) { val = x; }
+ }
+ public static ListNode reverseList(ListNode head) {
+ //使用两个指针
+ ListNode curr=head;
+ ListNode prev=null;
+ while(curr!=null){
+ //临时指针。用来存储下一个节点。
+ ListNode temp=curr.next;
+ curr.next=prev;
+ prev=curr;
+ curr=temp;
+ }
+ return prev;
+ }
+
+ public static void main(String[] args) {
+ ListNode a=new ListNode(5);
+ ListNode b=new ListNode(4);
+ ListNode c=new ListNode(3);
+ a.next=b;b.next=c;
+ ListNode result = reverseList(a);
+ for (ListNode node=result;node!=null;node=node.next){
+ System.out.println(node.val);
+ }
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution6.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution6.java
new file mode 100644
index 0000000..ebaa3a5
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution6.java
@@ -0,0 +1,49 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+/**
+ * @author xun2.liu
+ * @title: Solution6
+ * @projectName algorithm-study
+ * @description: 编写一个程序,找到两个单链表相交的起始节点。
+ * 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
+ * 输出:Reference of the node with value = 8
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists
+ * @date 2020/5/18 19:35
+ */
+public class Solution6 {
+ public static class ListNode {
+ int val;
+ ListNode next;
+ ListNode(int x) { val = x; }
+ }
+ public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
+ //使用两个指针分别指向headA、headB
+ //同时遍历两个连表
+ //当headA遍历完后指针指向headB,当headB遍历完后指针指向headA
+ //如此循环当两个指正都为Null的话代表没有相交的节点。
+ //如果都两个指针对应的节点相等就返回相等的节点就是相交的节点
+ ListNode p1=headA;
+ ListNode p2=headB;
+ while(p1!=p2){
+ p1=p1==null?headB:p1.next;
+ p2=p2==null?headA:p2.next;
+ }
+ return p1;
+ }
+
+ public static void main(String[] args) {
+ ListNode a=new ListNode(5);
+ ListNode b=new ListNode(4);
+ a.next=b;
+ ListNode c=new ListNode(6);
+ ListNode intersectionNode = getIntersectionNode(a, b);
+ if (null!=intersectionNode){
+ System.out.println(intersectionNode.val);
+ }else{
+ System.out.println("没有相交的节点哦");
+ }
+
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution7.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution7.java
new file mode 100644
index 0000000..4ccb886
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution7.java
@@ -0,0 +1,76 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+/**
+ * @author xun2.liu
+ * @title: Solution7
+ * @projectName algorithm-study
+ * @description: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
+ *
+ * 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
+ *
+ * 说明:不允许修改给定的链表。
+ *
+ * 示例 1:
+ *
+ * 输入:head = [1,2], pos = 0
+ * 输出:tail connects to node index 0
+ * 解释:链表中有一个环,其尾部连接到第一个节点。
+ *
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/linked-list-cycle-ii
+ *
+ * @date 2020/5/19 17:16
+ */
+public class Solution7 {
+ public static class ListNode {
+ int val;
+ ListNode next;
+ ListNode(int x) { val = x; }
+ }
+
+ /**
+ * 快慢指针遍历连表。看是否相遇。如果相遇在判断是否是循环链表。
+ * p1=x+y
+ * p2=x+y+z+y;
+ * 因为p2是p1的两倍
+ * 2*(x+y)=x+y+z+y
+ * x=z
+ * @param head
+ * @return
+ */
+ public static ListNode detectCycle(ListNode head) {
+ if (null== head || head.next==null){
+ return null;
+ }
+ //p1指针走一步、p2指针走两步。
+ ListNode p1=head;
+ ListNode p2=head;
+ while(p2!=null && p2.next!=null){
+ p1=p1.next;
+ p2=p2.next.next;
+ //如果相等就表示是环形。然后寻找环形入口。
+ if(p1==p2){
+ //p1指向头结点。找到环形入口
+ p1=head;
+ while(p1!=p2){
+ p1=p1.next;
+ p2=p2.next;
+ }
+ return p1;
+ }
+ }
+ return null;
+ }
+ public static void main(String[] args) {
+ ListNode a=new ListNode(5);
+ ListNode b=new ListNode(4);
+ ListNode c=new ListNode(6);
+ ListNode d=new ListNode(-1);
+ a.next=b;
+ b.next=c;
+ c.next=b;
+// c.next=b;
+ ListNode listNode = detectCycle(a);
+ System.out.println(listNode==null?"":listNode.val);
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution8.java b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution8.java
new file mode 100644
index 0000000..2a6a300
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/leetcode/Solution8.java
@@ -0,0 +1,68 @@
+package com.algorithm.study.demo.algorithm.leetcode;
+
+/**
+ * @author xun2.liu
+ * @title: Solution8
+ * @projectName algorithm-study
+ * @description: 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
+ *
+ * 示例:
+ * 给定一个链表: 1->2->3->4->5, 和 n = 2.
+ * 当删除了倒数第二个节点后,链表变为 1->2->3->5.
+ * 来源:力扣(LeetCode)
+ * 链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
+ * @date 2020/5/20 21:01
+ */
+public class Solution8 {
+ public static class ListNode {
+ int val;
+ ListNode next;
+ ListNode(int x) { val = x; }
+ }
+ /**
+ * 我们可以使用两个指针而不是一个指针。第一个指针从列表的开头向前移动 n+1步,而第二个指针将从列表的开头出发。现在,这两个指针被n个结点分开。
+ * 我们通过同时移动两个指针向前来保持这个恒定的间隔,直到第一个指针到达最后一个结点。此时第二个指针将指向从最后一个结点数起的第n个结点。
+ * 我们重新链接第二个指针所引用的结点的 next 指针指向该结点的下下个结点。
+ * @param head
+ * @param n
+ * @return
+ */
+ public static ListNode removeNthFromEnd(ListNode head, int n) {
+ if (head.next==null){
+ return null;
+ }
+ //增加一个头部节点,方便删除倒数的节点刚好是第一个节点。
+ ListNode temp=new ListNode(-1);
+ temp.next=head;
+ ListNode p1=temp;
+ ListNode p2=temp;
+ //第一个指针从列表的开头向前移动 n+1步
+ for (int i=0;i=0 && r=p1.length()?res:p1;
+ res=res.length()>=p2.length()?res:p2;
+ }
+ return res;
+ }
+ public static void main(String[] args) {
+ System.out.println(longestPalindrome("babad"));
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/algorithm/lz77/LZ77Codec.java b/src/main/java/com/algorithm/study/demo/algorithm/lz77/LZ77Codec.java
new file mode 100644
index 0000000..7c0c777
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/algorithm/lz77/LZ77Codec.java
@@ -0,0 +1,124 @@
+package com.algorithm.study.demo.algorithm.lz77;
+
+/**
+ * @author xun2.liu
+ * @title: LZ77Codec
+ * @projectName algorithm-study
+ * @description: LZ77算法实现
+ * @date 2019/11/25 0:54
+ */
+public class LZ77Codec {
+ /**
+ * 搜索最大相同字符串的辅助类
+ */
+ private class SearchResult{
+ public int off = 0;
+ public int length = 0;
+ }
+
+ /**
+ * search the max matched string in the slide window;
+ * 可以使用KMP算法提高效率
+ * @param s 需要编码的字符串
+ * @param currentPosition 当前位置
+ * @return
+ */
+ private SearchResult search(String s,int currentPosition){
+ SearchResult result = new SearchResult();
+ for (int i = 0; i < currentPosition; i++) {
+ SearchResult t = new SearchResult();
+ for (int j = i; j < currentPosition; j++) {
+ // 区别已匹配和没有匹配的情况
+ if(s.charAt(currentPosition+j-i)==s.charAt(j)){
+ // 已经匹配的话 length+1
+ // 没有匹配的话 length=1 并计算偏移量
+ if(t.length >0){
+ t.length++;
+ }else{
+ t.length=1;
+ // 计算偏移量
+ t.off = currentPosition - j;
+ }
+ }else {
+ break;
+ }
+ }
+ if(t.length>result.length){
+ result=t;
+ }
+ }
+ return result;
+ }
+ /**
+ * 编码
+ *
+ * 目前发现的问题
+ * 1. 从左往右扫描和从右往左扫描off可能不一样
+ * @param s 需要编码的字符串
+ * @return 已经编码的字符串
+ */
+ String encoding(String s) {
+ StringBuilder builder = new StringBuilder();
+ // set current coding position pointer to the start of message
+ int currentPosition = 0;
+ while (true){
+ // search the max matched string in the slide window;
+ SearchResult result = search(s,currentPosition);
+ System.out.println("result:"+result.off+" "+result.length+" "+s.substring(currentPosition,currentPosition+result.length+1));
+ Character nextChar = s.charAt(currentPosition+result.length);
+ if(result.length!=0){
+ builder.append("(").append(result.off).append(",").append(result.length).append(",").append(nextChar).append(")");
+ currentPosition+=result.length+1;
+ }else {
+ builder.append("(0,0,").append(nextChar).append(")");
+ currentPosition++;
+ }
+ if(currentPosition>=s.length()){
+ break;
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * 解码
+ * @param s 已经编码的字符串
+ * @return 已经解码的字符串
+ */
+ String decoding(String s) {
+ StringBuilder builder = new StringBuilder();
+ // 提取(off,length,next_char)
+ String[] arr = s.split("\\)\\(");
+ if (arr.length==0){
+ return "";
+ }
+ arr[0]=arr[0].substring(1,arr[0].length());
+ if(arr.length>1){
+ arr[arr.length-1]=arr[arr.length-1].substring(0,arr[arr.length-1].length()-1);
+ }
+ for(String it : arr){
+ String[] data = it.split(",");
+ Integer off = Integer.valueOf(data[0]);
+ Integer length = Integer.valueOf(data[1]);
+ String nextChar = data[2];
+ Integer iv = builder.length()-off;
+ for (int i = 0; i < length; i++) {
+ builder.append(builder.charAt(iv+i));
+ }
+ builder.append(nextChar);
+ System.out.println("decoding:"+iv+" "+ builder.toString());
+ }
+ return builder.toString();
+ }
+
+ public static void main(String[] args) {
+ LZ77Codec codec = new LZ77Codec();
+ String input = "AABCAABCCAABCE";
+// String output = "(0,0,A)(1,1,B)(0,0,C)(4,4,C)(5,4,E)";
+ String code = codec.encoding(input);
+ System.out.println(code);
+
+ String message = codec.decoding(code);
+ System.out.println(message);
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/AppleMobile.java b/src/main/java/com/algorithm/study/demo/base/AppleMobile.java
new file mode 100644
index 0000000..47dd67b
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/AppleMobile.java
@@ -0,0 +1,5 @@
+package com.algorithm.study.demo.base;
+
+public abstract class AppleMobile extends Mobile{
+
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/HuaweiMobile.java b/src/main/java/com/algorithm/study/demo/base/HuaweiMobile.java
new file mode 100644
index 0000000..c472308
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/HuaweiMobile.java
@@ -0,0 +1,13 @@
+package com.algorithm.study.demo.base;
+
+public class HuaweiMobile extends Mobile{
+
+ @Override
+ public void call() {
+ System.out.println("huawei call");
+ }
+ @Override
+ public void show(){
+ System.out.println("niubi show");
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/IPerson.java b/src/main/java/com/algorithm/study/demo/base/IPerson.java
new file mode 100644
index 0000000..34d7545
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/IPerson.java
@@ -0,0 +1,5 @@
+package com.algorithm.study.demo.base;
+
+public interface IPerson {
+ void eat();
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/IphoneXMobile.java b/src/main/java/com/algorithm/study/demo/base/IphoneXMobile.java
new file mode 100644
index 0000000..96d35fc
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/IphoneXMobile.java
@@ -0,0 +1,8 @@
+package com.algorithm.study.demo.base;
+
+public class IphoneXMobile extends AppleMobile {
+ @Override
+ public void call() {
+ System.out.println("iphonex call");
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/MainTest.java b/src/main/java/com/algorithm/study/demo/base/MainTest.java
new file mode 100644
index 0000000..e5798a7
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/MainTest.java
@@ -0,0 +1,22 @@
+package com.algorithm.study.demo.base;
+
+public class MainTest {
+ private static final String msgg="123";
+ public static void main(String[] args) {
+ MainTest mo=new MainTest();
+ Mobile mobile=new IphoneXMobile();
+ mobile.call();
+ mobile.show();
+
+ System.out.println(mobile);
+ Mobile mobile2=new HuaweiMobile();
+ mobile2.call();
+ mobile2.show();
+
+ System.out.println(mobile);
+
+
+ IPerson per = new YellowPerson();
+ per.eat();
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/Mobile.java b/src/main/java/com/algorithm/study/demo/base/Mobile.java
new file mode 100644
index 0000000..e77aebf
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/Mobile.java
@@ -0,0 +1,9 @@
+package com.algorithm.study.demo.base;
+
+public abstract class Mobile {
+ public abstract void call();
+
+ void show(){
+ System.out.println("show");
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/base/YellowPerson.java b/src/main/java/com/algorithm/study/demo/base/YellowPerson.java
new file mode 100644
index 0000000..4d6945a
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/base/YellowPerson.java
@@ -0,0 +1,8 @@
+package com.algorithm.study.demo.base;
+
+public class YellowPerson implements IPerson {
+ @Override
+ public void eat() {
+ System.out.println("kuaizi eat");
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/datastructure/linear/MLinkList.java b/src/main/java/com/algorithm/study/demo/datastructure/linear/MLinkList.java
index 24e70ba..94e67ab 100644
--- a/src/main/java/com/algorithm/study/demo/datastructure/linear/MLinkList.java
+++ b/src/main/java/com/algorithm/study/demo/datastructure/linear/MLinkList.java
@@ -19,113 +19,124 @@ public class Node {
// 无参构造器
public Node() {
}
+
// 初始化全部属性的构造器
public Node(E data, Node next) {
this.value = data;
this.next = next;
}
}
+
private Node data;// 保存头结点
- private int size=0;// 保存已含有的节点数
+ private int size = 0;// 保存已含有的节点数
- public MLinkList(){
- this.data=null;//初始化一个空的头结点
+ public MLinkList() {
+ this.data = null;//初始化一个空的头结点
}
/**
* 添加一个头结点
+ *
* @param element
*/
- public void addFirst(E element){
- if (data==null){
- data=new Node(element,null);
- }else{
- Node temp=new Node(element,null);
- temp.next=data;
- data=temp;
+ public void addFirst(E element) {
+ if (data == null) {
+ data = new Node(element, null);
+ } else {
+ Node temp = new Node(element, null);
+ temp.next = data;
+ data = temp;
}
size++;
}
+
/**
* 删除一个头结点
+ *
* @return
*/
- public E deleteFirst(){
- Node current=data;
- E val=current.value;
- current.value=current.next.value;
- current.next=current.next.next;
+ public E deleteFirst() {
+ Node current = data;
+ E val = current.value;
+ current.value = current.next.value;
+ current.next = current.next.next;
return val;
}
/**
* 在index插入节点
+ *
* @param index
* @param element
*/
- public void add(int index,E element){
+ public void add(int index, E element) {
checkPositionIndex(index);
- if (index==0){
+ if (index == 0) {
addFirst(element);
return;
}
- Node newNode=new Node(element,null);//新的结点
- Node current=data;//保存index当前的结点
- int i=1;//默认是第i个结点
- while (isize-1){
- throw new IndexOutOfBoundsException("数组越界Index: "+index+", Size: "+size);
+ if (index < 0 || index > size - 1) {
+ throw new IndexOutOfBoundsException("数组越界Index: " + index + ", Size: " + size);
}
}
- public int size(){
+
+ public int size() {
return size;
}
@Override
- public String toString(){
- StringBuilder sb=new StringBuilder();
- Node temp=data;
- while (temp!=null){
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Node temp = data;
+ while (temp != null) {
sb.append(temp.value);
- temp= temp.next;//找到最后一个结点
+ temp = temp.next;//找到最后一个结点
}
return sb.toString();
}
@@ -196,26 +212,26 @@ public String toString(){
/**
* 反转链表O(n)复杂度实现
*/
- public void reverseLinkedList(){
- if (data==null || data.next==null){
+ public void reverseLinkedList() {
+ if (data == null || data.next == null) {
return;
}
- Node p1=data;
- Node p2=data.next;
- Node p3=null;
- while (p2!=null){
- p3=p2.next;
- p2.next=p1;
- p1=p2;
- p2=p3;
+ Node p1 = data;
+ Node p2 = data.next;
+ Node p3 = null;
+ while (p2 != null) {
+ p3 = p2.next;
+ p2.next = p1;
+ p1 = p2;
+ p2 = p3;
}
- data.next=null;
- data=p1;
+ data.next = null;
+ data = p1;
System.out.println("反转完毕");
}
public static void main(String[] args) {
- MLinkList mLinkList=new MLinkList();
+ MLinkList mLinkList = new MLinkList();
mLinkList.add(4);
mLinkList.add(1);
mLinkList.add(8);
diff --git a/src/main/java/com/algorithm/study/demo/datastructure/tree/AVLBinTree.java b/src/main/java/com/algorithm/study/demo/datastructure/tree/AVLBinTree.java
deleted file mode 100644
index 87e47a4..0000000
--- a/src/main/java/com/algorithm/study/demo/datastructure/tree/AVLBinTree.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.algorithm.study.demo.datastructure.tree;
-
-/**
- * AVL二叉搜索
- * @Author: liuxun
- * @CreateDate: 2018/10/22 上午11:26
- * @Version: 1.0
- */
-public class AVLBinTree {
-}
diff --git a/src/main/java/com/algorithm/study/demo/datastructure/tree/LinkBinTree.java b/src/main/java/com/algorithm/study/demo/datastructure/tree/LinkBinTree.java
index 805abcc..ce3c9e4 100644
--- a/src/main/java/com/algorithm/study/demo/datastructure/tree/LinkBinTree.java
+++ b/src/main/java/com/algorithm/study/demo/datastructure/tree/LinkBinTree.java
@@ -1,29 +1,32 @@
package com.algorithm.study.demo.datastructure.tree;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.Stack;
+import com.alibaba.fastjson.JSON;
+import org.testng.collections.Lists;
+
+import java.util.*;
/**
- *
* 二叉搜索树链表存储
- 前序遍历:根节点->左子树->右子树
- 中序遍历:左子树->根节点->右子树
- 后序遍历:左子树->右子树->根节点
+ * 前序遍历:根节点->左子树->右子树
+ * 中序遍历:左子树->根节点->右子树
+ * 后序遍历:左子树->右子树->根节点
* Created by liuxun on 2017/6/29.
*/
public class LinkBinTree {
- public static class TreeNode{
+ public static class TreeNode {
Integer data;//节点数据
TreeNode left;//左子节点数据
TreeNode right;//右子节点数据
- TreeNode(){}
- TreeNode(Integer data){
+
+ TreeNode() {
+ }
+
+ TreeNode(Integer data) {
this.data = data;
this.left = null;
this.right = null;
}
+
public TreeNode(Integer data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
@@ -32,160 +35,194 @@ public TreeNode(Integer data, TreeNode left, TreeNode right) {
}
private TreeNode root;
- /**初始化空的二叉树**/
- public LinkBinTree(){
- root=new TreeNode();
+
+ /**
+ * 初始化空的二叉树
+ **/
+ public LinkBinTree() {
+ root = new TreeNode();
}
- /**指定一个默认的根二叉树**/
- public LinkBinTree(Integer d){
- root=new TreeNode(d);
+
+ /**
+ * 指定一个默认的根二叉树
+ **/
+ public LinkBinTree(Integer d) {
+ root = new TreeNode(d);
}
- /**判断二叉树是否为空**/
- public boolean isEmpty(){
- return root.data==null;
+
+ /**
+ * 判断二叉树是否为空
+ **/
+ public boolean isEmpty() {
+ return root.data == null;
}
- /**获取根节点**/
- public TreeNode getRoot(){
- if (isEmpty()){
+
+ /**
+ * 获取根节点
+ **/
+ public TreeNode getRoot() {
+ if (isEmpty()) {
throw new RuntimeException("树为空,无法获取根节点");
}
return root;
}
- /**获取树的深度**/
- public int getDeep(TreeNode t){
- if (t==null){
+ /**
+ * 获取树的深度
+ **/
+ public int getDeep(TreeNode t) {
+ if (t == null) {
return 0;
}
- int l=getDeep(t.left);
- int r=getDeep(t.right);
- return l>r?(l+1):(r+1);
+ int l = getDeep(t.left);
+ int r = getDeep(t.right);
+ return l > r ? (l + 1) : (r + 1);
}
- /**获取树的最小深度**/
- public int getMinDeep(TreeNode t){
- if (t==null){
+
+ /**
+ * 获取树的最小深度
+ **/
+ public int getMinDeep(TreeNode t) {
+ if (t == null) {
return 0;
}
- if (t.left==null && t.right==null){
+ if (t.left == null && t.right == null) {
return 1;
}
- int l=getMinDeep(t.left);
- int r=getMinDeep(t.right);
- return lt.data){
- if(t.right!=null){
- add(t.right,value);
- }
- else{
+
+ private void add(TreeNode t, int value) {
+ if (value > t.data) {
+ if (t.right != null) {
+ add(t.right, value);
+ } else {
t.right = new TreeNode(value);
}
- }
- else{
- if(t.left!=null){
- add(t.left,value);
- }
- else{
+ } else {
+ if (t.left != null) {
+ add(t.left, value);
+ } else {
t.left = new TreeNode(value);
}
}
}
- private void add2(TreeNode t,int value){
- TreeNode node=new TreeNode(value);
- TreeNode current=t;
- while(current!=null){
- TreeNode parentNode=current;
- if (current.data>value){
- current=current.left;
- if (current==null){
- parentNode.left=node;
+
+ private void add2(TreeNode t, int value) {
+ if (null == t.data) {
+ t.data = value;
+ return;
+ }
+ TreeNode node = new TreeNode(value);
+ TreeNode current = t;
+ while (true) {
+ TreeNode parentNode = current;
+ if (current.data > value) {
+ current = current.left;
+ if (current == null) {
+ parentNode.left = node;
return;
}
- }else{
- current=current.right;
- if (current==null){
- parentNode.right=node;
+ } else {
+ current = current.right;
+ if (current == null) {
+ parentNode.right = node;
return;
}
}
}
}
+
/**
* 递归从根节点开始插入数据,大于根节点放在右子树,小于根节点放在左子树
+ *
* @param value
*/
- public void add(int value){
- add(root,value);
+ public void add(int value) {
+ add(root, value);
}
+
/**
* 非递归模式插入数据
* 从根节点开始插入数据,大于根节点放在右子树,小于根节点放在左子树
+ *
* @param value
*/
- public void add2(int value){
- add2(root,value);
+ public void add2(int value) {
+ add2(root, value);
}
+
/**
* 前序遍历
* 如果树为空返回,如果不为空首先从根节点开始遍历,然后先前序遍历左子树,最后前序遍历右子树。
*/
- public void preOrderTraverse(TreeNode t){
- if (t==null) {
+ public void preOrderTraverse(TreeNode t) {
+ if (t == null) {
return;
}
System.out.println(t.data);
preOrderTraverse(t.left);
preOrderTraverse(t.right);
}
- public void preOrderTraverse(){
+
+ public void preOrderTraverse() {
preOrderTraverse(root);
}
/**
* 非递归前序遍历
+ *
* @param t
*/
public void preOrderTraverse2(TreeNode t) {
- if (t==null) {
+ if (t == null) {
return;
}
- Stack stack=new Stack<>();
- while(t!=null || !stack.isEmpty()){
- while (t!=null){
+ Stack stack = new Stack<>();
+ while (t != null || !stack.isEmpty()) {
+ while (t != null) {
System.out.println(t.data);
stack.push(t);
- t=t.left;
+ t = t.left;
}
- if (!stack.isEmpty()){
- t=stack.pop();
- t=t.right;
+ if (!stack.isEmpty()) {
+ t = stack.pop();
+ t = t.right;
}
}
}
- public void preOrderTraverse2(){
+
+ public void preOrderTraverse2() {
preOrderTraverse2(root);
}
@@ -193,64 +230,71 @@ public void preOrderTraverse2(){
* 中序遍历
* 如果树为空返回,从根节点开始,中序遍历左子树,然后访问根节点,最后中序遍历右子树。
*/
- public void inOrderTraverse(TreeNode t){
- if (t==null) {
+ public void inOrderTraverse(TreeNode t) {
+ if (t == null) {
return;
}
inOrderTraverse(t.left);
System.out.println(t.data);
inOrderTraverse(t.right);
}
- public void inOrderTraverse(){
+
+ public void inOrderTraverse() {
inOrderTraverse(root);
}
/**
* 非递归中序遍历
+ *
* @param t
*/
- public void inOrderTraverse2(TreeNode t){
- if (t==null) {
+ public void inOrderTraverse2(TreeNode t) {
+ if (t == null) {
return;
}
- Stack stack=new Stack<>();
- while (t!=null || !stack.isEmpty()){
- while (t!=null){
+ Stack stack = new Stack<>();
+ while (t != null || !stack.isEmpty()) {
+ while (t != null) {
stack.push(t);
- t=t.left;
+ t = t.left;
}
- if (!stack.isEmpty()){
- t=stack.pop();
+ if (!stack.isEmpty()) {
+ t = stack.pop();
System.out.println(t.data);
- t=t.right;
+ t = t.right;
}
}
}
- public void inOrderTraverse2(){
+
+ public void inOrderTraverse2() {
inOrderTraverse2(root);
}
+
/**
* 后续遍历
+ *
* @param t
*/
- public void postOrderTraverse(TreeNode t){
- if (t==null) {
+ public void postOrderTraverse(TreeNode t) {
+ if (t == null) {
return;
}
postOrderTraverse(t.left);
postOrderTraverse(t.right);
System.out.println(t.data);
}
- public void postOrderTraverse(){
+
+ public void postOrderTraverse() {
postOrderTraverse(root);
}
/**
* 非递归后续遍历
+ *
* @param root
*/
- public void postOrderTraverse2(TreeNode root){
+ public void postOrderTraverse2(TreeNode root) {
Stack s = new Stack();
Stack s2 = new Stack();
Integer i = new Integer(1); //0表示对应位置上的节点还没有遍历过右节点,1表示已经遍历过
@@ -273,63 +317,199 @@ public void postOrderTraverse2(TreeNode root){
}
}
}
- public void postOrderTraverse2(){
+
+ public void postOrderTraverse2() {
postOrderTraverse2(root);
}
+
/**
* 层级遍历
+ *
* @param t
*/
- public void divOrderTraverse(TreeNode t){
- if (t==null) {
- return;
+ public List> divOrderTraverse(TreeNode t) {
+ if (t == null) {
+ return new ArrayList>();
}
- Queue queue = new LinkedList() ;
+ //初始化队列只包含一个节点 root 和层次编号 0 : level = 0。
+ List> levels = new ArrayList<>();
+ Queue queue = new LinkedList();
queue.add(root);
- while(queue.size() != 0)
- {
+ //树的层数
+ int level = 0;
+ while (queue.size() != 0) {
+ //插入一个空列表,开始当前层的算法。
+ levels.add(new ArrayList<>());
int len = queue.size();
- for(int i=0;i > levelOrder(TreeNode root) {
+ if (root == null) {
+ return new ArrayList>();
+ }
+ List> lists = new ArrayList<>();
+ Queue queue = new LinkedList();
+ queue.offer(root);
+ while (queue.size() > 0) {
+ LinkedList levelList = new LinkedList<>();
+ for (int i = queue.size(); i > 0; i--) {
+ TreeNode node = queue.poll();
+ if ((lists.size() & 1) == 1) {
+ //奇数层放到队列尾部
+ levelList.addLast(node.data);
+ } else {
+ //偶数层放到队列头部
+ levelList.addFirst(node.data);
+ }
+ if (node.right != null) {
+ queue.offer(node.right);
+ }
+ if (node.left != null) {
+ queue.offer(node.left);
+ }
+ }
+ lists.add(levelList);
+ }
+ return lists;
+ }
+
+ /**
+ * 层级遍历1
+ */
+ public void divOrderTraverse() {
+ List> lists = divOrderTraverse(root);
+ System.out.println(JSON.toJSONString(lists));
+ }
+
+ /**
+ * 层级遍历2
+ */
+ public void levelOrder() {
+ List> lists = levelOrder(root);
+ System.out.println(JSON.toJSONString(lists));
+ }
+
+ /**
+ * 序列化树
+ *
+ * @param root
+ * @return
+ */
+ public String serialize(TreeNode root) {
+ if (root == null) {
+ return null;
+ }
+ //使用层序遍历
+ Queue que = new LinkedList();
+ StringBuilder sb = new StringBuilder("[");
+ que.add(root);
+ while (que.size() > 0) {
+ int currSize = que.size();
+ for (int i = 0; i < currSize; i++) {
+ TreeNode node = que.poll();
+ if (node != null) {
+ sb.append(node.data).append(",");
+ que.add(node.left);
+ que.add(node.right);
+ } else {
+ sb.append("null,");
+ }
+ }
+ }
+ return sb.deleteCharAt(sb.length() - 1).append("]").toString();
}
- /**区间搜索**/
- private void searchSection(TreeNode t,int k1,int k2,ArrayList result){
- if (t==null){
+
+ public String serialize() {
+ String serialize = serialize(root);
+ System.out.println(serialize);
+ return serialize;
+ }
+
+ // Decodes your encoded data to tree.
+ public TreeNode deserialize(String data) {
+ if (data == null || data.length() == 0) {
+ return null;
+ }
+ data = data.substring(1, data.length() - 1);
+ String[] arrData = data.split(",");
+ //填充根节点
+ TreeNode tree = new TreeNode(Integer.valueOf(arrData[0]));
+ Queue que = new LinkedList<>();
+ que.add(tree);
+ int i = 1;
+ while (que.size() > 0 && i < arrData.length) {
+ TreeNode currNode = que.poll();
+
+ if (arrData[i].equals("null")) {
+ currNode.left = null;
+ } else {
+ TreeNode treeLeft = new TreeNode(Integer.valueOf(arrData[i]));
+ currNode.left = treeLeft;
+ que.add(treeLeft);
+ }
+ i++;
+
+ if (arrData[i].equals("null")) {
+ currNode.right = null;
+ } else {
+ TreeNode treeRight = new TreeNode(Integer.valueOf(arrData[i]));
+ currNode.right = treeRight;
+ que.add(treeRight);
+ }
+ i++;
+ }
+ return tree;
+ }
+
+ /**
+ * 区间搜索
+ **/
+ private void searchSection(TreeNode t, int k1, int k2, ArrayList result) {
+ if (t == null) {
return;
}
- if(t.data>k1){
- searchSection(t.left,k1,k2,result);
+ if (t.data > k1) {
+ searchSection(t.left, k1, k2, result);
}
- if(t.data>=k1&&t.data<=k2){
+ if (t.data >= k1 && t.data <= k2) {
result.add(t.data);
}
- if(t.datakey){
- currnode=currnode.left;
- }else if (currnode.data key) {
+ currnode = currnode.left;
+ } else if (currnode.data < key) {
+ currnode = currnode.right;
+ } else {
return currnode;
}
}
@@ -338,39 +518,42 @@ public TreeNode find(int key){
/**
* 查找最小值
+ *
* @return
*/
- public TreeNode findMin(){
- TreeNode current=root;
- TreeNode minNode=current;
- while(current!=null){
- minNode=current;
- current=current.left;
+ public TreeNode findMin() {
+ TreeNode current = root;
+ TreeNode minNode = current;
+ while (current != null) {
+ minNode = current;
+ current = current.left;
}
return minNode;
}
/**
* 查找最大值
+ *
* @return
*/
- public TreeNode findMax(){
- TreeNode current=root;
- TreeNode maxNode=current;
- while(current!=null){
- maxNode=current;
- current=current.right;
+ public TreeNode findMax() {
+ TreeNode current = root;
+ TreeNode maxNode = current;
+ while (current != null) {
+ maxNode = current;
+ current = current.right;
}
return maxNode;
}
+
public static void main(String[] args) {
- int[] ls=new int[]{30,9,8};
- LinkBinTree linkBinTree=new LinkBinTree(ls[0]);
- for (int i=1;i list=new ArrayList();
// linkBinTree.searchSection(linkBinTree.getRoot(),10,20,list);
// System.out.println("区间查询"+list.toString());
-// System.out.println("-------------递归遍历----------------");
+ System.out.println("-------------递归遍历----------------");
// linkBinTree.preOrderTraverse();//前序遍历 从根节点开始遍历
-// System.out.println("-----------------------------");
+ System.out.println("-----------------------------");
// linkBinTree.inOrderTraverse();//中序遍历 从根节点开始
-// System.out.println("-----------------------------");
+ System.out.println("-----------------------------");
// linkBinTree.postOrderTraverse();//后序遍历
-// System.out.println("-----------------------------");
+ System.out.println("-----------------------------");
// linkBinTree.divOrderTraverse();//层次遍历
+// linkBinTree.levelOrder();
+ //序列化、反序列化树
+ System.out.println("-----------------------------");
+ TreeNode deserializeTree = linkBinTree.deserialize(linkBinTree.serialize());
+ linkBinTree.levelOrder(deserializeTree);
// //前序遍历:根节点->左子树->右子树
// //中序遍历:左子树->根节点->右子树
// //后序遍历:左子树->右子树->根节点
// System.out.println();
// System.out.println("-------------非递归遍历----------------");
- linkBinTree.preOrderTraverse2();//前序遍历
+// linkBinTree.preOrderTraverse2();//前序遍历
// System.out.println("-----------------------------");
// linkBinTree.inOrderTraverse2();//中序遍历
// System.out.println("-----------------------------");
// linkBinTree.postOrderTraverse2();//后序遍历
- //二叉查找树搜索
- TreeNode node = linkBinTree.find(9);
- System.out.println(node.data);
- System.out.println("最小值为:"+linkBinTree.findMin().data);
+ //二叉查找树搜索
+// TreeNode node = linkBinTree.find(9);
+// System.out.println(node.data);
+// System.out.println("最小值为:"+linkBinTree.findMin().data);
+
}
}
diff --git a/src/main/java/com/algorithm/study/demo/enums/Calculator.java b/src/main/java/com/algorithm/study/demo/enums/Calculator.java
new file mode 100644
index 0000000..2e4a0c2
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/enums/Calculator.java
@@ -0,0 +1,15 @@
+package com.algorithm.study.demo.enums;
+
+/**
+ * @author xun2.liu
+ * @title: Calculator
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2020/1/7 14:51
+ */
+public class Calculator{
+
+ public int apply(int a, int b,Operator operator) {
+ return operator.apply(a,b);
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/enums/MainTest.java b/src/main/java/com/algorithm/study/demo/enums/MainTest.java
new file mode 100644
index 0000000..85a7c04
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/enums/MainTest.java
@@ -0,0 +1,19 @@
+package com.algorithm.study.demo.enums;
+
+import java.text.ParseException;
+
+/**
+ * @author xun2.liu
+ * @title: MainTest
+ * @projectName algorithm-study
+ * @description: 枚举类解决IF ESLE问题
+ * @date 2019/12/13 16:32
+ */
+public class MainTest{
+ public static void main(String[] args) throws ParseException {
+ Calculator calculator=new Calculator();
+ int result=calculator.apply(2,4,Operator.ADD);
+ System.out.println(result);
+ }
+
+}
diff --git a/src/main/java/com/algorithm/study/demo/enums/Operator.java b/src/main/java/com/algorithm/study/demo/enums/Operator.java
new file mode 100644
index 0000000..54201b9
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/enums/Operator.java
@@ -0,0 +1,48 @@
+package com.algorithm.study.demo.enums;
+
+/**
+ * @author xun2.liu
+ * @title: Operator
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/12/13 16:31
+ */
+public enum Operator {
+
+ ADD {
+ @Override
+ public int apply(int a, int b) {
+ return a + b;
+ }
+ },
+
+ MULTIPLY {
+ @Override
+ public int apply(int a, int b) {
+ return a * b;
+ }
+ },
+
+ SUBTRACT {
+ @Override
+ public int apply(int a, int b) {
+ return a - b;
+ }
+ },
+
+ DIVIDE {
+ @Override
+ public int apply(int a, int b) {
+ return a / b;
+ }
+ },
+
+ MODULO {
+ @Override
+ public int apply(int a, int b) {
+ return a % b;
+ }
+ };
+
+ public abstract int apply(int a, int b);
+}
\ No newline at end of file
diff --git a/src/main/java/com/algorithm/study/demo/guava/MainTest.java b/src/main/java/com/algorithm/study/demo/guava/MainTest.java
new file mode 100644
index 0000000..445274e
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/guava/MainTest.java
@@ -0,0 +1,40 @@
+//package com.algorithm.study.demo.guava;
+//
+//import com.github.rholder.retry.*;
+//import com.google.common.base.Predicates;
+//
+//import java.io.*;
+//import java.text.SimpleDateFormat;
+//import java.time.LocalDateTime;
+//import java.time.format.DateTimeFormatter;
+//import java.util.concurrent.ExecutionException;
+//import java.util.concurrent.TimeUnit;
+//
+///**
+// * guava 重试机制
+// * @Author: liuxun
+// * @CreateDate: 2019/1/2 上午11:29
+// * @Version: 1.0
+// */
+//public class MainTest {
+// public static void main(String[] args) {
+// //定义重试机制
+// Retryer retryer = RetryerBuilder.newBuilder()
+// .retryIfException() //设置异常重试
+// .retryIfResult(Predicates.equalTo(true)) //call方法返回true重试
+// .withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS)) //设置10秒后重试
+// .withStopStrategy(StopStrategies.stopAfterAttempt(3)).build(); //设置重试次数 超过将出异常
+// try {
+// retryer.call(() -> {
+// //这里写你的业务逻辑代码
+// System.out.println("11111111111111111122222");
+// return true; //需要重试返回true
+// });
+// } catch (ExecutionException e) {
+// e.printStackTrace();
+// } catch (RetryException e) {
+// e.printStackTrace();
+// }
+// }
+//}
+//
diff --git a/src/main/java/com/algorithm/study/demo/java8/FunctionTest.java b/src/main/java/com/algorithm/study/demo/java8/FunctionTest.java
new file mode 100644
index 0000000..1706fae
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/java8/FunctionTest.java
@@ -0,0 +1,95 @@
+package com.algorithm.study.demo.java8;
+
+import org.testng.Assert;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * @author xun2.liu
+ * @title: FunctionTest
+ * @projectName algorithm-study
+ * @description: Consumer实例
+ * @date 2019/12/20 15:19
+ */
+public class FunctionTest {
+ public static void main(String[] args) {
+// consumerTest();
+ functionTest();
+ }
+
+ /***
+ * Consumer是一个函数式编程接口; 顾名思义,Consumer的意思就是消费,即针对某个东西我们来使用它,因此它包含有一个有输入而无输出的accept接口方法;
+ * 除accept方法,它还包含有andThen这个方法;
+ */
+ public static void consumerTest() {
+ Consumer f = System.out::println;
+ Consumer f2 = n -> System.out.println(n + "-F2");
+
+ //执行完F后再执行F2的Accept方法
+ f.andThen(f2).accept("test");
+
+ //连续执行F的Accept方法
+// f.andThen(f).andThen(f).andThen(f).accept("test1");
+ }
+
+ /**
+ * Function测试
+ * Function也是一个函数式编程接口;它代表的含义是“函数”,而函数经常是有输入输出的,因此它含有一个apply方法,
+ * 包含一个输入与一个输出;除apply方法外,它还有compose与andThen及indentity三个方法
+ */
+ public static void functionTest() {
+ Function f = s -> s++;
+ Function g = s -> s * 2;
+
+ /**
+ * 下面表示在执行F时,先执行G,并且执行F时使用G的输出当作输入。
+ * 相当于以下代码:
+ * Integer a = g.apply(1);
+ * System.out.println(f.apply(a));
+ */
+ System.out.println(f.compose(g).apply(1));
+
+ /**
+ * 表示执行F的Apply后使用其返回的值当作输入再执行G的Apply;
+ * 相当于以下代码
+ * Integer a = f.apply(1);
+ * System.out.println(g.apply(a));
+ */
+ System.out.println(f.andThen(g).apply(1));
+
+ /**
+ * identity方法会返回一个不进行任何处理的Function,即输出与输入值相等;
+ */
+ System.out.println(Function.identity().apply("a"));
+ }
+
+
+
+ /**
+ * Predicate测试
+ * Predicate为函数式接口,predicate的中文意思是“断定”,即判断的意思,判断某个东西是否满足某种条件;
+ * 因此它包含test方法,根据输入值来做逻辑判断,其结果为True或者False。
+ */
+ private static void predicateTest() {
+ Predicate p = o -> o.equals("test");
+ Predicate g = o -> o.startsWith("t");
+
+ /**
+ * negate: 用于对原来的Predicate做取反处理;
+ * 如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;
+ */
+ Assert.assertFalse(p.negate().test("test"));
+
+ /**
+ * and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
+ */
+ Assert.assertTrue(p.and(g).test("test"));
+
+ /**
+ * or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
+ */
+ Assert.assertTrue(p.or(g).test("ta"));
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/model/User.java b/src/main/java/com/algorithm/study/demo/model/User.java
index ae11880..99395ee 100644
--- a/src/main/java/com/algorithm/study/demo/model/User.java
+++ b/src/main/java/com/algorithm/study/demo/model/User.java
@@ -6,7 +6,8 @@
public class User {
private int id;
private String name;
-
+ public User(){
+ }
public User(int id,String name){
this.id=id;
this.name=name;
diff --git a/src/main/java/com/algorithm/study/demo/testng/Test.java b/src/main/java/com/algorithm/study/demo/testng/Test.java
new file mode 100644
index 0000000..2f1f84a
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/testng/Test.java
@@ -0,0 +1,11 @@
+package com.algorithm.study.demo.testng;
+
+import com.algorithm.study.demo.thread.SleepUtils;
+
+public class Test {
+
+ @org.testng.annotations.Test(threadPoolSize = 10, invocationCount = 10000)
+ public void testJsf(){
+ System.out.println("asdklfjalskfdj"+Thread.currentThread().getName());
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/thread/ThreadTest.java b/src/main/java/com/algorithm/study/demo/thread/ThreadTest.java
new file mode 100644
index 0000000..29aeda9
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/thread/ThreadTest.java
@@ -0,0 +1,7 @@
+package com.algorithm.study.demo.thread;
+
+public class ThreadTest {
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/util/DateUtils.java b/src/main/java/com/algorithm/study/demo/util/DateUtils.java
new file mode 100644
index 0000000..dbca451
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/util/DateUtils.java
@@ -0,0 +1,43 @@
+package com.algorithm.study.demo.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @title: DateUtils
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/8/30 11:14
+ */
+public class DateUtils {
+ private static final String formatStr = "HH:mm";
+ public static void main(String args[]) throws ParseException {
+ String tS = "11:00";
+ String tE = "12:10";
+ System.out.println(getLong(tS));
+ System.out.println(getLong(tE));
+ System.out.println(getCurrentTime());
+ System.out.println(isInZone(getLong(tS),getLong(tE),getCurrentTime()));
+ if(isInZone(getLong(tS),getLong(tE),getCurrentTime())){
+ System.out.println("当前时间在范围中");
+ }else{
+ System.out.println("当前时间不在范围中");
+ }
+ }
+
+ private static boolean isInZone(long tStart,long tEnd,long t) throws ParseException {
+ return t>=tStart && t<=tEnd;
+ }
+
+ private static long getLong(String timeStr) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat(formatStr);
+ return dateFormat.parse(timeStr).getTime();
+ }
+
+ private static long getCurrentTime() throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat(formatStr);
+ return getLong(dateFormat.format(new Date()));
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/util/GZIPUtils.java b/src/main/java/com/algorithm/study/demo/util/GZIPUtils.java
new file mode 100644
index 0000000..15c1fe5
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/util/GZIPUtils.java
@@ -0,0 +1,225 @@
+package com.algorithm.study.demo.util;
+
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Maps;
+import org.apache.commons.io.FileUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.zip.*;
+
+/**
+ * @title: GZIPUtils
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/10/17 20:50
+ */
+public class GZIPUtils {
+
+ /**
+ * 使用gzip进行压缩
+ */
+ public static String gzip(String primStr) {
+ if (primStr == null || primStr.length() == 0) {
+ return primStr;
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ GZIPOutputStream gzip = null;
+ try {
+ gzip = new GZIPOutputStream(out);
+ gzip.write(primStr.getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (gzip != null) {
+ try {
+ gzip.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ return new sun.misc.BASE64Encoder().encode(out.toByteArray());
+ }
+
+ /**
+ * Description:使用gzip进行解压缩
+ *
+ * @param compressedStr
+ * @return
+ */
+ public static String gunzip(String compressedStr) {
+ if (compressedStr == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = null;
+ GZIPInputStream ginzip = null;
+ byte[] compressed = null;
+ String decompressed = null;
+ try {
+ compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
+ in = new ByteArrayInputStream(compressed);
+ ginzip = new GZIPInputStream(in);
+
+ byte[] buffer = new byte[1024];
+ int offset = -1;
+ while ((offset = ginzip.read(buffer)) != -1) {
+ out.write(buffer, 0, offset);
+ }
+ decompressed = out.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (ginzip != null) {
+ try {
+ ginzip.close();
+ } catch (IOException e) {
+ }
+ }
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ return decompressed;
+ }
+
+ /**
+ * 使用zip进行压缩
+ *
+ * @param str 压缩前的文本
+ * @return 返回压缩后的文本
+ */
+ public static final String zip(String str) {
+ if (str == null) {
+ return null;
+ }
+ byte[] compressed;
+ ByteArrayOutputStream out = null;
+ ZipOutputStream zout = null;
+ String compressedStr = null;
+ try {
+ out = new ByteArrayOutputStream();
+ zout = new ZipOutputStream(out);
+ zout.putNextEntry(new ZipEntry("0"));
+ zout.write(str.getBytes());
+ zout.closeEntry();
+ compressed = out.toByteArray();
+ compressedStr = new sun.misc.BASE64Encoder().encodeBuffer(compressed);
+ } catch (IOException e) {
+ compressed = null;
+ } finally {
+ if (zout != null) {
+ try {
+ zout.close();
+ } catch (IOException e) {
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return compressedStr;
+ }
+
+ /**
+ * 使用zip进行解压缩
+ *
+ * @param compressedStr 压缩后的文本
+ * @return 解压后的字符串
+ */
+ public static final String unzip(String compressedStr) {
+ if (compressedStr == null) {
+ return null;
+ }
+ ByteArrayOutputStream out = null;
+ ByteArrayInputStream in = null;
+ ZipInputStream zin = null;
+ String decompressed = null;
+ try {
+ byte[] compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
+ out = new ByteArrayOutputStream();
+ in = new ByteArrayInputStream(compressed);
+ zin = new ZipInputStream(in);
+ zin.getNextEntry();
+ byte[] buffer = new byte[1024];
+ int offset = -1;
+ while ((offset = zin.read(buffer)) != -1) {
+ out.write(buffer, 0, offset);
+ }
+ decompressed = out.toString();
+ } catch (IOException e) {
+ decompressed = null;
+ } finally {
+ if (zin != null) {
+ try {
+ zin.close();
+ } catch (IOException e) {
+ }
+ }
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return decompressed;
+ }
+
+ public static void main(String[] args) throws IOException {
+ //78910.txt 123456.txt
+ String strOld = FileUtils.readFileToString(new File("D:/78910.txt"), "utf-8");
+ System.out.println("压缩前长度:"+strOld.length());
+ String gzip = zip(strOld);
+ System.out.println("压缩后长度:"+gzip.length());
+ String unzip = unzip(gzip);
+ FileUtils.write(new File("D:/2234567.txt"),unzip,"UTF-8");
+// int num=10000;
+//
+// long beginTime = System.currentTimeMillis();
+// for (int i = 0; i < num; i++) {
+// zip(strOld);
+// }
+// long endTime = System.currentTimeMillis();
+// System.out.println("压缩总耗时"+(endTime - beginTime));
+// System.out.println("压缩平均耗时"+(endTime - beginTime) / 10000);
+//
+// long currentTimeMillis = System.currentTimeMillis();
+// for (int i = 0; i < 10000; i++) {
+// unzip(gzip);
+// }
+// long endTimeMillis = System.currentTimeMillis();
+// System.out.println("解压总耗时"+(endTimeMillis - currentTimeMillis));
+// System.out.println("解压平均耗时"+(endTimeMillis - currentTimeMillis) / 10000);
+
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/util/JodaTimeUtil.java b/src/main/java/com/algorithm/study/demo/util/JodaTimeUtil.java
new file mode 100644
index 0000000..04432fc
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/util/JodaTimeUtil.java
@@ -0,0 +1,106 @@
+package com.algorithm.study.demo.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import java.util.Date;
+
+/**
+ * @description: JodaTime工具类
+ * @date 2019/5/31 11:24
+ **/
+public class JodaTimeUtil {
+ public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ public static final String STANDARD_DAY_FORMAT = "yyyy-MM-dd";
+ public static final String STANDARD_DAY_FORMAT_1 = "yyyyMMdd";
+ public static final String STANDARD_MILLIS_FORMAT="yyyy-MM-dd HH:mm:ss.SSS";
+ public static final String STANDARD_MINUTE_FORMAT="yyyyMMddHHmm";
+
+ public static Date strToDate(String dateTimeStr,String formatStr){
+ DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr);
+ DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
+ return dateTime.toDate();
+ }
+ public static DateTime dateToDateTime(Date date){
+ DateTime dateTime = new DateTime(date);
+ return dateTime;
+ }
+ public static Date strToDate(String dateTimeStr){
+ DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT);
+ DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
+ return dateTime.toDate();
+ }
+ public static Date getNow(){
+ return DateTime.now().toDate();
+ }
+ public static String getNowFormat(String formatStr){
+ return DateTime.now().toString(formatStr);
+ }
+ public static String getFormatNow(){
+ return DateTime.now().toString(STANDARD_DAY_FORMAT_1);
+ }
+ public static String getFormatNowDay(){
+ return DateTime.now().toString(STANDARD_DAY_FORMAT);
+ }
+
+ public static Long strToMillis(String dateTimeStr,String formatStr){
+ DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr);
+ long dateTime = dateTimeFormatter.parseDateTime(dateTimeStr).getMillis();
+ return dateTime;
+ }
+
+ public static String dateToStr(Date date,String formatStr){
+ if(date == null){
+ return StringUtils.EMPTY;
+ }
+ DateTime dateTime = new DateTime(date);
+ return dateTime.toString(formatStr);
+ }
+ public static String dateStrToMinuteStr(String dateTimeStr,String formatStr1,String formatStr2){
+ DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr1);
+ DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
+ return dateTime.toString(formatStr2);
+ }
+
+
+
+ public static String dateToStr(Date date){
+ if(date == null){
+ return StringUtils.EMPTY;
+ }
+ DateTime dateTime = new DateTime(date);
+ return dateTime.toString(STANDARD_FORMAT);
+ }
+
+ /**
+ * 解析日期 yyyy-MM-dd HH:mm:ss
+ *
+ * @param timestamp
+ * @return
+ */
+ public static String format(Long timestamp, String pattern) {
+ String dateStr = "";
+ if (null == timestamp || timestamp.longValue() < 0) {
+ return dateStr;
+ }
+ try {
+ Date date = new Date(timestamp);
+ dateStr=dateToStr(date,pattern);
+ } catch (Exception e) {
+ // ignore
+ }
+ return dateStr;
+ }
+ public static DateTime strToDateTime(String dateTimeStr,String formatStr){
+ Date date = strToDate(dateTimeStr, formatStr);
+ return dateToDateTime(date);
+ }
+
+ public static void main(String[] args) {
+ Date createTime = JodaTimeUtil.strToDate("2019-10-24 02:04:41.921", JodaTimeUtil.STANDARD_MILLIS_FORMAT);
+ DateTime dateTime = dateToDateTime(createTime);
+ System.out.println(dateTime.getHourOfDay());
+ }
+}
diff --git a/src/main/java/com/algorithm/study/demo/util/Paging.java b/src/main/java/com/algorithm/study/demo/util/Paging.java
index c1c6427..0c96ffe 100644
--- a/src/main/java/com/algorithm/study/demo/util/Paging.java
+++ b/src/main/java/com/algorithm/study/demo/util/Paging.java
@@ -72,4 +72,7 @@ public int getStart() {
return Math.max((page - 1) * pageSize, 0);
}
+ public static void main(String[] args) {
+
+ }
}
diff --git a/src/main/java/com/algorithm/study/demo/util/ZipUtil.java b/src/main/java/com/algorithm/study/demo/util/ZipUtil.java
new file mode 100644
index 0000000..765e78b
--- /dev/null
+++ b/src/main/java/com/algorithm/study/demo/util/ZipUtil.java
@@ -0,0 +1,54 @@
+package com.algorithm.study.demo.util;
+
+/**
+ * @title: ZipUtil
+ * @projectName algorithm-study
+ * @description: TODO
+ * @date 2019/10/18 13:39
+ */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+// 将一个字符串按照zip方式压缩和解压缩
+public class ZipUtil {
+
+ // 压缩
+ public static String compress(String str) throws IOException {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ GZIPOutputStream gzip = new GZIPOutputStream(out);
+ gzip.write(str.getBytes());
+ gzip.close();
+ return out.toString("ISO-8859-1");
+ }
+
+ // 解压缩
+ public static String uncompress(String str) throws IOException {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(str
+ .getBytes("ISO-8859-1"));
+ GZIPInputStream gunzip = new GZIPInputStream(in);
+ byte[] buffer = new byte[256];
+ int n;
+ while ((n = gunzip.read(buffer)) >= 0) {
+ out.write(buffer, 0, n);
+ }
+ // toString()使用平台默认编码,也可以显式的指定如toString("GBK")
+ return out.toString();
+ }
+
+ // 测试方法
+ public static void main(String[] args) throws IOException {
+ System.out.println(ZipUtil.compress("中国China"));
+ System.out.println(ZipUtil.uncompress(ZipUtil.compress("中国China")));
+ }
+
+}