diff --git a/src/leo/class10_16/BFS.java b/src/leo/class10_16/BFS.java new file mode 100644 index 0000000..ba0771f --- /dev/null +++ b/src/leo/class10_16/BFS.java @@ -0,0 +1,71 @@ +package leo.class10_16; + +import leo.class10_16.Graph.Node; + +import java.util.*; + +/** + * @author Leo + * @ClassName BFS + * @DATE 2020/12/29 2:23 下午 + * @Description 图的宽度优先遍历 + * + */ +public class BFS { + + /** + * 功能描述 : 深度优先遍历 借助set, + * 过滤掉已经遍历过的节点 + * 出队列就打印 + * @author Leo + * @date 2020/12/29 2:28 下午 + * @param node + * @return void + */ + public static void bfs(Node node) { + if (node == null) { + return; + } + Queue queue = new LinkedList<>(); + HashSet set = new HashSet<>(); + queue.offer(node); + set.add(node); + Node cur = null; + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.println(cur.value); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + set.add(next); + queue.offer(next); + } + } + + } + + + } + + public static void bfs1(Node node) { + if (node == null) { + return; + } + Queue queue = new LinkedList<>(); + Set set = new HashSet<>(); + queue.offer(node); + set.add(node); + Node cur; + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.println(cur.value); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + set.add(next); + queue.offer(next); + } + } + } + + } + +} diff --git a/src/leo/class10_16/DFS.java b/src/leo/class10_16/DFS.java new file mode 100644 index 0000000..8a30b47 --- /dev/null +++ b/src/leo/class10_16/DFS.java @@ -0,0 +1,74 @@ +package leo.class10_16; + +import leo.class10_16.Graph.Node; + +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +/** + * @author Leo + * @ClassName DFS + * @DATE 2020/12/29 2:29 下午 + * @Description 深度优先遍历 + */ +public class DFS { + + /** + * 功能描述 : 深度优先遍历 + * 入栈就打印 + * @author Leo + * @date 2020/12/29 2:34 下午 + * @param node + * @return void + */ + public static void dfs(Node node) { + if (node == null) { + return; + } + Stack stack = new Stack<>(); + HashSet set = new HashSet<>(); + set.add(node); + stack.push(node); + Node cur; + System.out.println(node.value); + while (!stack.isEmpty()) { + cur = stack.pop(); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + set.add(next); + /** + * 栈永远放着整条路径 + */ + stack.push(cur); + stack.push(next); + System.out.println(next.value); + break; + } + } + } + } + + public static void dfs1(Node node) { + if (node == null) { + return; + } + Stack stack = new Stack<>(); + Set set = new HashSet<>(); + stack.push(node); + set.add(node); + System.out.println(node.value); + Node cur; + while (!stack.isEmpty()) { + cur = stack.pop(); + for (Node next : cur.nexts) { + if (!set.contains(next)) { + stack.push(next); + set.add(next); + System.out.println(next.value); + break; + } + } + } + } +} diff --git a/src/leo/class10_16/Dijkstra.java b/src/leo/class10_16/Dijkstra.java new file mode 100644 index 0000000..95a452a --- /dev/null +++ b/src/leo/class10_16/Dijkstra.java @@ -0,0 +1,15 @@ +package leo.class10_16; + +/** + * @author Leo + * @ClassName Dijkstra + * @DATE 2020/12/30 10:05 上午 + * @Description Dijkstra算法 + * 又向无负权重,可以有环,<环路的权重累加和没有负数> + * 1)Dijkstra算法必须指定一个源点 + * 2)生成一个源点到各个点的最小距离表,一开始只有一条记录,即原点到自己的最小距离为0,源点到其他所有点的最小距离都为正无穷大 + * 3)从距离表中拿出没拿过记录里的最小记录,通过这个点发出的边,更新源点到各个点的最小距离表,不断重复这一步 + * 4)源点到所有的点记录如果都被拿过一遍,过程停止,最小距离表得到了 + */ +public class Dijkstra { +} diff --git a/src/leo/class10_16/Graph/Edge.java b/src/leo/class10_16/Graph/Edge.java new file mode 100644 index 0000000..e7735b0 --- /dev/null +++ b/src/leo/class10_16/Graph/Edge.java @@ -0,0 +1,30 @@ +package leo.class10_16.Graph; + +/** + * @author Leo + * @ClassName Edge + * @DATE 2020/12/29 1:57 下午 + * @Description + */ +public class Edge { + /** + * 边的权重 + */ + public int weight; + + /** + * 从哪个节点出发 + */ + public Node from; + + /** + * 到哪个节点 + */ + public Node to; + + public Edge(int weight, Node from, Node to) { + this.weight = weight; + this.from = from; + this.to = to; + } +} diff --git a/src/leo/class10_16/Graph/Graph.java b/src/leo/class10_16/Graph/Graph.java new file mode 100644 index 0000000..96542b7 --- /dev/null +++ b/src/leo/class10_16/Graph/Graph.java @@ -0,0 +1,34 @@ +package leo.class10_16.Graph; + +import java.util.HashMap; +import java.util.HashSet; + +/** + * @author Leo + * @ClassName Graph + * @DATE 2020/12/29 2:00 下午 + * @Description 图:由点集合边集组成 + * + * 1.邻接表法 + * 2.邻接矩阵法 + * 3.除此之外还有其他众多的方式 + */ +public class Graph { + /** + * 点集 + * key:为点结构的值 + * value:key对应的点结构 + */ + public HashMap nodes; + + /** + * 边集 + * 边集不重复 + */ + public HashSet edges; + + public Graph() { + nodes = new HashMap<>(); + edges = new HashSet<>(); + } +} diff --git a/src/leo/class10_16/Graph/GraphGenerator.java b/src/leo/class10_16/Graph/GraphGenerator.java new file mode 100644 index 0000000..65093bf --- /dev/null +++ b/src/leo/class10_16/Graph/GraphGenerator.java @@ -0,0 +1,71 @@ +package leo.class10_16.Graph; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Leo + * @ClassName GraphGenerator + * @DATE 2020/12/29 2:08 下午 + * @Description 创建图 + */ +public class GraphGenerator { + + /** + * 功能描述 : 数组邻接矩阵法创建图结构 + * @author Leo + * @date 2020/12/29 2:08 下午 + * @param matrix matrix[i] = [weight,formValue,toValue] + * @return leo.class10_16.Graph.Graph + */ + public static Graph createGraph(int[][] matrix) { + Graph graph = new Graph(); + for (int i = 0; i < matrix.length; i++) { + int weight = matrix[i][0]; + int form = matrix[i][1]; + int to = matrix[i][2]; + if (!graph.nodes.containsKey(form)) { + graph.nodes.put(form, new Node(form)); + } + if (!graph.nodes.containsKey(to)) { + graph.nodes.put(form, new Node(to)); + } + Node formNode = graph.nodes.get(form); + Node toNode = graph.nodes.get(to); + Edge edge = new Edge(weight, formNode, toNode); + formNode.nexts.add(toNode); + formNode.out++; + toNode.in++; + formNode.edges.add(edge); + graph.edges.add(edge); + } + return graph; + } + + class Train { + public Graph createGraph(int[][] matrix) { + Graph graph = new Graph(); + for (int i = 0; i < matrix.length; i++) { + int weight = matrix[i][0]; + int from = matrix[i][0]; + int to = matrix[i][0]; + if (!graph.nodes.containsKey(from)) { + graph.nodes.put(from, new Node(from)); + } + if (!graph.nodes.containsKey(to)) { + graph.nodes.put(to, new Node(to)); + } + Node fromNode = graph.nodes.get(from); + Node toNode = graph.nodes.get(to); + Edge edge = new Edge(weight, fromNode, toNode); + fromNode.nexts.add(toNode); + fromNode.out++; + toNode.in++; + fromNode.edges.add(edge); + graph.edges.add(edge); + } + return graph; + } + + } +} diff --git a/src/leo/class10_16/Graph/Node.java b/src/leo/class10_16/Graph/Node.java new file mode 100644 index 0000000..30f75e7 --- /dev/null +++ b/src/leo/class10_16/Graph/Node.java @@ -0,0 +1,43 @@ +package leo.class10_16.Graph; + +import java.util.ArrayList; + +/** + * @author Leo + * @ClassName Node + * @DATE 2020/12/29 1:53 下午 + * @Description 点结构 + */ +public class Node { + + /** + * 值 + */ + public int value; + /** + * 入度:指有多少边指向该节点 + */ + public int in; + /** + * 出度:有多少条边指向其他点 + */ + public int out; + + /** + * 邻居:从该节点出发可以到达的点为邻居 + */ + public ArrayList nexts; + + /** + * 从该节点出发有哪些边 + */ + public ArrayList edges; + + public Node(int value) { + this.value = value; + this.in = 0; + this.out = 0; + this.nexts = new ArrayList<>(); + this.edges = new ArrayList<>(); + } +} diff --git a/src/leo/class10_16/Kruskal.java b/src/leo/class10_16/Kruskal.java new file mode 100644 index 0000000..ec80f06 --- /dev/null +++ b/src/leo/class10_16/Kruskal.java @@ -0,0 +1,95 @@ +package leo.class10_16; + +import leo.class10_16.Graph.Edge; +import leo.class10_16.Graph.Graph; +import leo.class10_16.Graph.Node; + +import java.util.*; + +/** + * @author Leo + * @ClassName Kruskal + * @DATE 2020/12/29 5:46 下午 + * @Description 最小生成树算法之Kruskal + * 1)总是从权值最小的边开始考虑,依次考察权值依次变大的边 + * 2)当前的边要么进入最小生成树的集合,要么丢弃 + * 3)如果当前的边进入最小生成树的集合中不会形成环,就要当前边 + * 4)如果当前的边进入最小生成树的集合中会形成环,就不要当前边 + * 5)考察完所有边之后,最小生成树的集合也得到了 + */ +public class Kruskal { + + class Code{ + + class UnionFind{ + Map parentMap; + Map sizeMap; + + public UnionFind(Collection nodes) { + parentMap = new HashMap<>(); + sizeMap = new HashMap<>(); + Iterator iterator = nodes.iterator(); + while (iterator.hasNext()) { + Node cur = iterator.next(); + parentMap.put(cur, cur); + sizeMap.put(cur, 0); + } + } + + public Node find(Node node) { + Stack stack = new Stack<>(); + while (node != parentMap.get(node)) { + stack.push(node); + node = parentMap.get(node); + } + while (!stack.isEmpty()) { + parentMap.put(stack.pop(), node); + } + return node; + } + + public boolean isSameSet(Node n1, Node n2) { + return find(n1) == find(n2); + } + + public void union(Node n1, Node n2) { + Node aF = find(n1); + Node bF = find(n2); + if (n1 == n2) { + return; + } + int aSize = sizeMap.get(aF); + int bSize = sizeMap.get(bF); + Node big = aSize >= bSize ? aF : bF; + Node small = big == aF ? bF : aF; + parentMap.put(small, big); + sizeMap.put(big, aSize + bSize); + sizeMap.remove(small); + } + + + + } + public Set kruskalMST(Graph graph){ + UnionFind unionFind = new UnionFind(graph.nodes.values()); + PriorityQueue queue = new PriorityQueue<>((o1,o2)->{return o1.weight - o2.weight;}); + for (Edge edge : graph.edges) { + queue.offer(edge); + } + Set set = new HashSet<>(); + while (!queue.isEmpty()) { + Edge edge = queue.poll(); + if (!unionFind.isSameSet(edge.from, edge.to)) { + set.add(edge); + unionFind.union(edge.from, edge.to); + } + } + return set; + } + + + + + } + +} diff --git a/src/leo/class10_16/Prim.java b/src/leo/class10_16/Prim.java new file mode 100644 index 0000000..65536de --- /dev/null +++ b/src/leo/class10_16/Prim.java @@ -0,0 +1,64 @@ +package leo.class10_16; + +import com.sun.org.apache.regexp.internal.RE; +import leo.class10_16.Graph.Edge; +import leo.class10_16.Graph.Graph; +import leo.class10_16.Graph.Node; + +import java.util.HashSet; +import java.util.PriorityQueue; +import java.util.Set; + +/** + * @author Leo + * @ClassName Prim + * @DATE 2020/12/30 10:04 上午 + * @Description 最小生成树算法之Prim + * 1)可以从任意节点出发来寻找最小生成树 + * 2)某个点加入到被选取的点中后,解锁这个点出发的所有新的边 + * 3)在所有解锁的边中选最小的边,然后看看这个边会不会形成环 + * 4)如果会,不要当前边,继续考察剩下解锁的边中最小的边,重复3) + * 5)如果不会,要当前边,将该边的指向点加入到被选取的点中,重复2) + * 6)当所有点都被选取,最小生成树就得到了 + * + */ +public class Prim { + + + public static Set primMST(Graph graph) { + //根据权重排序 小根堆 + PriorityQueue queue = new PriorityQueue<>((o1, o2) -> {return o1.weight - o2.weight;}); + for (Edge edge : graph.edges) { + queue.offer(edge); + } + Set set = new HashSet<>(); + Set result = new HashSet<>(); + for (Node node : graph.nodes.values()) { + //点解锁边 + if (!set.contains(node)) { + for (Edge edge : node.edges) { + queue.offer(edge); + } + } + //边解锁点 + while (!queue.isEmpty()) { + Edge edge = queue.poll(); + Node toNode = edge.to; + //点又解锁边 + if (!set.contains(toNode)) { + set.add(toNode); + result.add(edge); + for (Edge e : toNode.edges) { + queue.offer(e); + } + } + + } + // 如果要防森林,就加上break,如果确定是一个图,就取消break + //break + + } + + return result; + } +} diff --git a/src/leo/class10_16/TopologicalOrder.java b/src/leo/class10_16/TopologicalOrder.java new file mode 100644 index 0000000..f2ace9a --- /dev/null +++ b/src/leo/class10_16/TopologicalOrder.java @@ -0,0 +1,245 @@ +package leo.class10_16; + +import leo.class10_16.Graph.Graph; +import leo.class10_16.Graph.Node; + +import java.lang.reflect.Array; +import java.util.*; + +/** + * @author Leo + * @ClassName TopologicalOrder + * @DATE 2020/12/29 3:13 下午 + * @Description 拓扑排序 有向无环图 + * 要求:有向图且其中没有环 + * 应用:事件安排、编译顺序 + * 点次的概念: + * xSum>ySum + * xSum为x为头走过的点的总数 + * ySum为y为头走过的点的总数 + * 如果xSum>ySum x的拓扑序小于等于y的拓扑序 + * https://www.lintcode.com/problem/topological-sorting + */ +public class TopologicalOrder { + /* + 1)在图中找到所有入度为0的点输出 + 2)把所有入度为0的点在图中删掉,继续找入度为0的点输出,周而复始 + 3)图的所有点都被删除后,依次输出的顺序就是拓扑排序 + */ + static class Sort{ + public static List sortedTopology(Graph graph) { + //入度map + HashMap inMap = new HashMap<>(); + //入度入度为零的队列 + Queue zeroQueue = new LinkedList<>(); + //变量所有node得到in为0的节点,加入到队列中 + for (Node node : graph.nodes.values()) { + inMap.put(node, node.in); + if (node.in == 0) { + zeroQueue.offer(node); + } + } + + List list = new ArrayList<>(); + + while (!zeroQueue.isEmpty()) { + Node cur = zeroQueue.poll(); + //将入度为零的节点加入到结果中 + list.add(cur); + for (Node next : cur.nexts) { + //将当前节点的邻居节点的入度减一 + inMap.put(next, inMap.get(next) - 1); + //再次将入度为零的节点加入到队列中 + if (next.in == 0) { + zeroQueue.offer(next); + } + } + } + return list; + } + + } + + + + /** + * 点次的概念: + * xSum>ySum + * xSum为x为头走过的点的总数 + * ySum为y为头走过的点的总数 + * 如果xSum>ySum x的拓扑序小于等于y的拓扑序 + */ + static class DFS_Count { + + static class Record{ + //节点 + DirectedGraphNode node; + //节点的点次 + long count; + + public Record(DirectedGraphNode node, long deep) { + this.node = node; + this.count = deep; + } + } + /* + * @param graph: A list of Directed graph node + * @return: Any topological order for the given graph. + */ + public ArrayList topSort(ArrayList graph) { + //点次缓存表,结果表 + HashMap order = new HashMap<>(); + for (DirectedGraphNode node : graph) { + findRecord(node, order); + } + ArrayList recordList = new ArrayList<>(); + for (Record record : order.values()) { + recordList.add(record); + } + recordList.sort(new MyComparator()); + ArrayList list = new ArrayList<>(); + for (Record record : recordList) { + list.add(record.node); + } + return list; + } + + /** + * 功能描述 : 获取cur节点所到之处的点次 + * @author Leo + * @date 2020/12/29 4:47 下午 + * @param cur 当前节点 + * @param order 缓存 + * @return Record (当前节点,点次) + */ + public static Record findRecord(DirectedGraphNode cur, HashMap order) { + //查询缓存中是否存在,如果存在直接返回 + if (order.containsKey(cur)) { + return order.get(cur); + } + //如果没有 开始计算 + long count = 0; + for (DirectedGraphNode next : cur.neighbors) { + count += findRecord(next, order).count; + } + //最后要加上自己的点次 + Record record = new Record(cur, count+1); + //加入缓存 + order.put(cur, record); + return record; + } + + //倒序 + static class MyComparator implements Comparator { + + @Override + public int compare(Record o1, Record o2) { + return o1.count == o2.count ? 0 :(o1.count > o2.count ? -1 : 1); + } + + } + } + + /** + * 最大深度 + * xDeep >= yDeep + * xDeep 是以x头的最大深度 + * yDeep 是以y头的最大深度 + * 如果xDeep >= yDeep x的拓扑序小于等于y的拓扑序 + */ + class DFS_Deep { + + class Record{ + DirectedGraphNode node; + int deep; + + public Record(DirectedGraphNode node, int deep) { + this.node = node; + this.deep = deep; + } + } + + public ArrayList topSort(ArrayList graph) { + HashMap order = new HashMap<>(); + for (DirectedGraphNode node : graph) { + findRecord(node, order); + } + ArrayList records = new ArrayList<>(); + for (Record record : order.values()) { + records.add(record); + } + records.sort((o1,o2)->{return o2.deep - o1.deep;}); + ArrayList list = new ArrayList<>(); + for (Record record : records) { + list.add(record.node); + } + return list; + } + + public Record findRecord(DirectedGraphNode cur, HashMap order) { + + if (order.containsKey(cur)) { + return order.get(cur); + } + int deep = 0; + for (DirectedGraphNode next : cur.neighbors) { + deep = Math.max(deep, findRecord(next, order).deep); + } + Record record = new Record(cur, deep + 1); + order.put(cur, record); + return record; + } + + + } + + class BFS{ + public ArrayList topSort(ArrayList graph) { + Map map = new HashMap<>(); + Queue zeroQueue = new LinkedList<>(); + for (DirectedGraphNode node : graph) { + map.put(node, 0); + } + for (DirectedGraphNode node : graph) { + for (DirectedGraphNode next : node.neighbors) { + map.put(next, map.get(next) + 1); + } + } + for (DirectedGraphNode node : map.keySet()) { + if (map.get(node) == 0) { + zeroQueue.offer(node); + } + } + ArrayList list = new ArrayList<>(); + DirectedGraphNode cur; + while (!zeroQueue.isEmpty()) { + cur = zeroQueue.poll(); + list.add(cur); + for (DirectedGraphNode next : cur.neighbors) { + map.put(next, map.get(next) - 1); + if (map.get(next) == 0) { + zeroQueue.offer(next); + } + } + } + return list; + } + } + + + /** + * @author Leo + * @date 2020/12/29 4:39 下午 + * + */ + public static class DirectedGraphNode { + public int label; + public ArrayList neighbors; + + public DirectedGraphNode(int x) { + label = x; + neighbors = new ArrayList(); + } + } + +} diff --git a/src/leo/class10_17/Dijkstra.java b/src/leo/class10_17/Dijkstra.java new file mode 100644 index 0000000..c623aad --- /dev/null +++ b/src/leo/class10_17/Dijkstra.java @@ -0,0 +1,10 @@ +package leo.class10_17; + +/** + * @author Leo + * @ClassName Dijkstra + * @DATE 2020/12/30 11:16 上午 + * @Description + */ +public class Dijkstra { +} diff --git a/src/leo/class10_17/Edge.java b/src/leo/class10_17/Edge.java new file mode 100644 index 0000000..085eb5b --- /dev/null +++ b/src/leo/class10_17/Edge.java @@ -0,0 +1,19 @@ +package leo.class10_17; + +/** + * @author Leo + * @ClassName Edge + * @DATE 2020/12/30 10:59 上午 + * @Description 边结构 + */ +public class Edge { + public int weight; + public Node from; + public Node to; + + public Edge(int weight, Node from, Node to) { + this.weight = weight; + this.from = from; + this.to = to; + } +} diff --git a/src/leo/class10_17/Graph.java b/src/leo/class10_17/Graph.java new file mode 100644 index 0000000..264a8ad --- /dev/null +++ b/src/leo/class10_17/Graph.java @@ -0,0 +1,22 @@ +package leo.class10_17; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +/** + * @author Leo + * @ClassName Graph + * @DATE 2020/12/30 11:01 上午 + * @Description 图结构 + */ +public class Graph { + + public HashMap nodes; + public HashSet edges; + + public Graph() { + nodes = new HashMap<>(); + edges = new HashSet<>(); + } +} diff --git a/src/leo/class10_17/Node.java b/src/leo/class10_17/Node.java new file mode 100644 index 0000000..4e0be98 --- /dev/null +++ b/src/leo/class10_17/Node.java @@ -0,0 +1,26 @@ +package leo.class10_17; + +import java.util.ArrayList; + +/** + * @author Leo + * @ClassName Node + * @DATE 2020/12/30 10:58 上午 + * @Description 点结构 + */ +public class Node { + + public int value; + public int in; + public int out; + public ArrayList nodes; + public ArrayList edges; + + public Node(int value) { + this.value = value; + this.in = 0; + this.out = 0; + this.nodes = new ArrayList<>(); + this.edges = new ArrayList<>(); + } +} diff --git a/src/leo/class11_17/Hanoi.java b/src/leo/class11_17/Hanoi.java new file mode 100644 index 0000000..6e5518d --- /dev/null +++ b/src/leo/class11_17/Hanoi.java @@ -0,0 +1,38 @@ +package leo.class11_17; + +import class11_17.Code01_Hanoi; + +/** + * @author Leo + * @ClassName Hanoi + * @DATE 2020/12/30 11:17 上午 + * @Description 汉诺塔问题 + */ +public class Hanoi { + + public static void hanoi(int n) { + if (n == 0) { + return; + } + process(n, "left", "right", "mid"); + } + + private static void process(int n, String form, String to, String other) { + if (n == 1) { + System.out.println("move " + 1 + " " + form + " =>" + to); + }else{ + process(n - 1, form, other, to); + System.out.println("move " + n + " " + form + " =>" + to); + process(n - 1, other, to, form); + } + + } + public static void main(String[] args){ + int n = 3; + hanoi(n); + System.out.println("-------"); + Code01_Hanoi.hanoi2(n); + } + + +} diff --git a/src/leo/class11_17/PrintStr.java b/src/leo/class11_17/PrintStr.java new file mode 100644 index 0000000..50197b0 --- /dev/null +++ b/src/leo/class11_17/PrintStr.java @@ -0,0 +1,131 @@ +package leo.class11_17; + +import java.nio.file.Path; +import java.util.*; + +/** + * @author Leo + * @ClassName PrintAllSubsquences + * @DATE 2020/12/30 11:16 上午 + * @Description 打印字符串的问题 + */ +public class PrintStr { + + /** + * 打印一个字符串的全部子序列 + */ + static class Subs{ + public static List subs(String string) { + List list = new ArrayList<>(); + if (string == null) { + return list; + } + char[] chars = string.toCharArray(); + String path = ""; + p(chars, 0, list, path); + return list; + } + + private static void p(char[] chars, int i, List list, String path) { + if (i == chars.length) { + list.add(path); + return; + }; + p(chars, i + 1, list, path); + p(chars, i + 1, list, path + String.valueOf(chars[i])); + } + + } + + /** + * 打印一个字符串的全部子序列,要求不要出现重复字面值的子序列 + */ + static class SubNoRepeat { + public static List subNoRepeat(String string) { + List list = new ArrayList<>(); + if (string == null) { + return list; + } + HashSet set = new HashSet<>(); + char[] chars = string.toCharArray(); + String path = ""; + p(chars, 0, set, path); + Iterator iterator = set.iterator(); + while (iterator.hasNext()) { + list.add(iterator.next()); + } + return list; + } + + private static void p(char[] chars, int i, HashSet set, String path) { + if (i == chars.length) { + set.add(path); + return; + } else { + p(chars, i + 1, set, path); + p(chars, i + 1, set, path + String.valueOf(chars[i])); + } + + } + } + + /** + * 打印一个字符串的全部排列 + */ + static class Permutations{ + + } + + /** + * 打印一个字符串的全部排列,要求不要出现重复的排列 + */ + static class PermutationsNoRepeat{ + + public static String[] permutation(String s) { + if (s == null || s.length() == 0) { + return new String[]{}; + } + char[] chars = s.toCharArray(); + List list = new ArrayList<>(); + f(chars,0,list); + return list.toArray(new String[list.size()]); + } + + public static void f(char[] chars,int i,List list) { + if (i == chars.length) { + list.add(String.valueOf(chars)); + }else { + boolean[] verify = new boolean[26]; + for (int j = i; j < chars.length; j++) { + if (!verify[chars[j] - 'a']) { + verify[chars[j] - 'a'] = true; + swap(chars, i, j); + f(chars, i + 1, list); + swap(chars, i, j); + } + } + } + } + + private static void swap(char[] chars,int i,int j) { + if (chars[i] == chars[j] || i == j) { + return; + } + char tmp = chars[i]; + chars[i] = chars[j]; + chars[j] = tmp; + } + + } + public static void main(String[] args){ + String str = "abcc"; + List subs = Subs.subs(str); + System.out.println(subs.toString()); + List subNoRepeat = SubNoRepeat.subNoRepeat(str); + System.out.println(subNoRepeat.toString()); + + String[] permutation = PermutationsNoRepeat.permutation(str); + System.out.println(new ArrayList(Arrays.asList(permutation)).toString()); + + } +} diff --git a/src/leo/class11_17/ReverseStackUsingRecursive.java b/src/leo/class11_17/ReverseStackUsingRecursive.java new file mode 100644 index 0000000..5012459 --- /dev/null +++ b/src/leo/class11_17/ReverseStackUsingRecursive.java @@ -0,0 +1,50 @@ +package leo.class11_17; + +import java.util.Stack; + +/** + * @author Leo + * @ClassName ReverseStackUsingRecursive + * @DATE 2020/12/30 2:46 下午 + * @Description + * 给你一个栈,请你逆序这个栈, + * 不能申请额外的数据结构, + * 只能使用递归函数 + */ +public class ReverseStackUsingRecursive { + + static class Code{ + public static void reverse(Stack stack) { + if (stack.isEmpty()) { + return; + } + int i = f(stack); + reverse(stack); + stack.push(i); + } + + private static int f(Stack stack) { + int value = stack.pop(); + if (stack.isEmpty()){ + return value; + } + int last = f(stack); + stack.push(value); + return last; + } + } + + + public static void main(String[] args){ + Stack stack = new Stack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + Code.reverse(stack); + System.out.println(stack); + + } + + +}