update on 2020-05-10

pull/3/head
algorithmzuo 5 years ago
parent 173a95b19f
commit 1862154ce0

@ -56,6 +56,7 @@ public class Code05_MaxSubBSTHead {
return process(head).maxSubBSTHead;
}
// 每一棵子树
public static class Info {
public Node maxSubBSTHead;
public int maxSubBSTSize;
@ -70,14 +71,14 @@ public class Code05_MaxSubBSTHead {
}
}
public static Info process(Node head) {
if (head == null) {
public static Info process(Node X) {
if (X == null) {
return null;
}
Info leftInfo = process(head.left);
Info rightInfo = process(head.right);
int min = head.value;
int max = head.value;
Info leftInfo = process(X.left);
Info rightInfo = process(X.right);
int min = X.value;
int max = X.value;
Node maxSubBSTHead = null;
int maxSubBSTSize = 0;
if (leftInfo != null) {
@ -94,9 +95,9 @@ public class Code05_MaxSubBSTHead {
maxSubBSTSize = rightInfo.maxSubBSTSize;
}
}
if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == head.left && leftInfo.max < head.value))
&& (rightInfo == null ? true : (rightInfo.maxSubBSTHead == head.right && rightInfo.min > head.value))) {
maxSubBSTHead = head;
if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == X.left && leftInfo.max < X.value))
&& (rightInfo == null ? true : (rightInfo.maxSubBSTHead == X.right && rightInfo.min > X.value))) {
maxSubBSTHead = X;
maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize)
+ (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1;
}

@ -30,7 +30,9 @@ public class Code06_IsCBT {
r = head.right;
if (
// 如果遇到了不双全的节点之后,又发现当前节点不是叶节点
(leaf && !(l == null && r == null)) || (l == null && r != null)) {
(leaf && (l != null || r != null)) || (l == null && r != null)
) {
return false;
}
if (l != null) {
@ -53,6 +55,7 @@ public class Code06_IsCBT {
return process(head).isCBT;
}
// 对每一棵子树,是否是满二叉树、是否是完全二叉树、高度
public static class Info {
public boolean isFull;
public boolean isCBT;
@ -65,28 +68,48 @@ public class Code06_IsCBT {
}
}
public static Info process(Node head) {
if (head == null) {
public static Info process(Node X) {
if (X == null) {
return new Info(true, true, 0);
}
Info leftInfo = process(head.left);
Info rightInfo = process(head.right);
Info leftInfo = process(X.left);
Info rightInfo = process(X.right);
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
boolean isFull = leftInfo.isFull
&&
rightInfo.isFull
&& leftInfo.height == rightInfo.height;
boolean isCBT = false;
if (isFull) {
isCBT = true;
} else {
} else { // 以x为头整棵树不满
if (leftInfo.isCBT && rightInfo.isCBT) {
if (leftInfo.isCBT && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) {
if (leftInfo.isCBT
&& rightInfo.isFull
&& leftInfo.height == rightInfo.height + 1) {
isCBT = true;
}
if (leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) {
if (leftInfo.isFull
&&
rightInfo.isFull
&& leftInfo.height == rightInfo.height + 1) {
isCBT = true;
}
if (leftInfo.isFull && rightInfo.isCBT && leftInfo.height == rightInfo.height) {
if (leftInfo.isFull
&& rightInfo.isCBT && leftInfo.height == rightInfo.height) {
isCBT = true;
}
}
}
return new Info(isFull, isCBT, height);

@ -20,6 +20,7 @@ public class Code07_lowestAncestor {
if (head == null) {
return null;
}
// key的父节点是value
HashMap<Node, Node> parentMap = new HashMap<>();
parentMap.put(head, null);
fillParentMap(head, parentMap);
@ -52,6 +53,7 @@ public class Code07_lowestAncestor {
return process(head, o1, o2).ans;
}
// 任何子树,
public static class Info {
public Node ans;
public boolean findO1;
@ -64,15 +66,19 @@ public class Code07_lowestAncestor {
}
}
public static Info process(Node head, Node o1, Node o2) {
if (head == null) {
public static Info process(Node X, Node o1, Node o2) {
if (X == null) {
return new Info(null, false, false);
}
Info leftInfo = process(head.left, o1, o2);
Info rightInfo = process(head.right, o1, o2);
boolean findO1 = head == o1 || leftInfo.findO1 || rightInfo.findO1;
boolean findO2 = head == o2 || leftInfo.findO2 || rightInfo.findO2;
Info leftInfo = process(X.left, o1, o2);
Info rightInfo = process(X.right, o1, o2);
boolean findO1 = X == o1 || leftInfo.findO1 || rightInfo.findO1;
boolean findO2 = X == o2 || leftInfo.findO2 || rightInfo.findO2;
// O1和O2最初的交汇点在哪
// 1) 在左树上已经提前交汇了
// 2) 在右树上已经提前交汇了
// 3) 没有在左树或者右树上提前交汇O1 O2 全了
// 4)
Node ans = null;
if (leftInfo.ans != null) {
ans = leftInfo.ans;
@ -82,7 +88,7 @@ public class Code07_lowestAncestor {
}
if (ans == null) {
if (findO1 && findO2) {
ans = head;
ans = X;
}
}
return new Info(ans, findO1, findO2);

@ -23,7 +23,14 @@ public class Code01_LowestLexicography {
return lowest;
}
public static void process(String[] strs, HashSet<Integer> use, String path, ArrayList<String> all) {
// strs里放着所有的字符串
// 已经使用过的字符串的下标在use里登记了不要再使用了
// 之前使用过的字符串,拼接成了-> path
// 用all收集所有可能的拼接结果
public static void process(String[] strs,
HashSet<Integer> use,
String path,
ArrayList<String> all) {
if (use.size() == strs.length) {
all.add(path);
} else {

@ -11,17 +11,23 @@ public class Code02_Light {
return process(road.toCharArray(), 0, new HashSet<>());
}
// str[index....]位置,自由选择放灯还是不放灯
// str[0..index-1]位置呢已经做完决定了那些放了灯的位置存在lights里
// 要求选出能照亮所有.的方案,并且在这些有效的方案中,返回最少需要几个灯
public static int process(char[] str, int index, HashSet<Integer> lights) {
if (index == str.length) {
if (index == str.length) { // 结束的时候
for (int i = 0; i < str.length; i++) {
if (str[i] != 'X') {
if (!lights.contains(i - 1) && !lights.contains(i) && !lights.contains(i + 1)) {
if (str[i] != 'X') { // 当前位置是点的话
if (!lights.contains(i - 1)
&& !lights.contains(i)
&& !lights.contains(i + 1)) {
return Integer.MAX_VALUE;
}
}
}
return lights.size();
} else {
} else { // str还没结束
// i X .
int no = process(str, index + 1, lights);
int yes = Integer.MAX_VALUE;
if (str[index] == '.') {
@ -40,7 +46,7 @@ public class Code02_Light {
while (index < str.length) {
if (str[index] == 'X') {
index++;
} else {
} else { // i -> .
light++;
if (index + 1 == str.length) {
break;

@ -22,11 +22,19 @@ public class Code04_BestArrange {
return process(programs, 0, 0);
}
// 还剩什么会议都放在programs里
// done 之前已经安排了多少会议,数量
// timeLine目前来到的时间点是什么
// 目前来到timeLine的时间点已经安排了done多的会议剩下的会议programs可以自由安排
// 返回能安排的最多会议数量
public static int process(Program[] programs, int done, int timeLine) {
if (programs.length == 0) {
return done;
}
// 还有会议可以选择
int max = done;
// 当前安排的会议是什么会,每一个都枚举
for (int i = 0; i < programs.length; i++) {
if (programs[i].start >= timeLine) {
Program[] next = copyButExcept(programs, i);

@ -20,14 +20,15 @@ public class Code01_UnionFind {
public HashMap<Node<V>, Integer> sizeMap;
public UnionSet(List<V> values) {
for (V value : values) {
Node<V> node = new Node<>(value);
nodes.put(value, node);
for (V cur : values) {
Node<V> node = new Node<>(cur);
nodes.put(cur, node);
parents.put(node, node);
sizeMap.put(node, 1);
}
}
// 从点cur开始一直往上找找到不能再往上的代表点返回
public Node<V> findFather(Node<V> cur) {
Stack<Node<V>> path = new Stack<>();
while (cur != parents.get(cur)) {
@ -57,15 +58,11 @@ public class Code01_UnionFind {
if (aHead != bHead) {
int aSetSize = sizeMap.get(aHead);
int bSetSize = sizeMap.get(bHead);
if (aSetSize >= bSetSize) {
parents.put(bHead, aHead);
sizeMap.put(aHead, aSetSize + bSetSize);
sizeMap.remove(bHead);
} else {
parents.put(aHead, bHead);
sizeMap.put(bHead, aSetSize + bSetSize);
sizeMap.remove(aHead);
}
Node<V> big = aSetSize >= bSetSize ? aHead : bHead;
Node<V> small = big == aHead ? bHead : aHead;
parents.put(small, big);
sizeMap.put(big, aSetSize + bSetSize);
sizeMap.remove(small);
}
}
}

@ -13,8 +13,10 @@ public class Code03_TopologySort {
// key某一个node
// value剩余的入度
HashMap<Node, Integer> inMap = new HashMap<>();
// 入度为0的点才能进这个队列
// 剩余入度为0的点才能进这个队列
Queue<Node> zeroInQueue = new LinkedList<>();
for (Node node : graph.nodes.values()) {
inMap.put(node, node.in);
if (node.in == 0) {

@ -1,11 +1,9 @@
package class10;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.Stack;
@ -13,46 +11,6 @@ import java.util.Stack;
//undirected graph only
public class Code04_Kruskal {
public static class MySets{
public HashMap<Node, List<Node>> setMap;
public MySets(List<Node> nodes) {
for(Node cur : nodes) {
List<Node> set = new ArrayList<Node>();
set.add(cur);
setMap.put(cur, set);
}
}
public boolean isSameSet(Node from, Node to) {
List<Node> fromSet = setMap.get(from);
List<Node> toSet = setMap.get(to);
return fromSet == toSet;
}
public void union(Node from, Node to) {
List<Node> fromSet = setMap.get(from);
List<Node> toSet = setMap.get(to);
for(Node toNode : toSet) {
fromSet.add(toNode);
setMap.put(toNode, fromSet);
}
}
}
// Union-Find Set
public static class UnionFind {
// key 某一个节点, value key节点往上的节点

@ -19,22 +19,23 @@ public class Code05_Prim {
public static Set<Edge> primMST(Graph graph) {
// 解锁的边进入小根堆
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(
new EdgeComparator());
HashSet<Node> set = new HashSet<>();
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
// 哪些点被解锁出来了
HashSet<Node> nodeSet = new HashSet<>();
Set<Edge> result = new HashSet<>(); // 依次挑选的的边在result里
for (Node node : graph.nodes.values()) { // 随便挑了一个点
// node 是开始点
if (!set.contains(node)) {
set.add(node);
if (!nodeSet.contains(node)) {
nodeSet.add(node);
for (Edge edge : node.edges) { // 由一个点,解锁所有相连的边
priorityQueue.add(edge);
}
while (!priorityQueue.isEmpty()) {
Edge edge = priorityQueue.poll(); // 弹出解锁的边中,最小的边
Node toNode = edge.to; // 可能的一个新的点
if (!set.contains(toNode)) { // 不含有的时候,就是新的点
set.add(toNode);
if (!nodeSet.contains(toNode)) { // 不含有的时候,就是新的点
nodeSet.add(toNode);
result.add(edge);
for (Edge nextEdge : toNode.edges) {
priorityQueue.add(nextEdge);

@ -7,15 +7,16 @@ import java.util.Map.Entry;
// no negative weight
public class Code06_Dijkstra {
public static HashMap<Node, Integer> dijkstra1(Node head) {
public static HashMap<Node, Integer> dijkstra1(Node from) {
// 从head出发到所有点的最小距离
// key : 从head出发到达key
// value : 从head出发到达key的最小距离
// 如果在表中没有T的记录含义是从head出发到T这个点的距离为正无穷
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(head, 0);
distanceMap.put(from, 0);
// 已经求过距离的节点存在selectedNodes中以后再也不碰
HashSet<Node> selectedNodes = new HashSet<>();
// from 0
Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
@ -24,7 +25,8 @@ public class Code06_Dijkstra {
if (!distanceMap.containsKey(toNode)) {
distanceMap.put(toNode, distance + edge.weight);
} else {
distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
distanceMap.put(edge.to,
Math.min(distanceMap.get(toNode), distance + edge.weight));
}
}
selectedNodes.add(minNode);
@ -33,7 +35,9 @@ public class Code06_Dijkstra {
return distanceMap;
}
public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap, HashSet<Node> touchedNodes) {
public static Node getMinDistanceAndUnselectedNode(
HashMap<Node, Integer> distanceMap,
HashSet<Node> touchedNodes) {
Node minNode = null;
int minDistance = Integer.MAX_VALUE;
for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
@ -59,7 +63,7 @@ public class Code06_Dijkstra {
public static class NodeHeap {
private Node[] nodes; // 实际的堆结构
// key 某一个node value 上面数组中的位置
// key 某一个node value 上面中的位置
private HashMap<Node, Integer> heapIndexMap;
// key 某一个节点, value 从源节点出发到该节点的目前最小距离
private HashMap<Node, Integer> distanceMap;
@ -103,7 +107,8 @@ public class Code06_Dijkstra {
}
private void insertHeapify(Node node, int index) {
while (distanceMap.get(nodes[index]) < distanceMap.get(nodes[(index - 1) / 2])) {
while (distanceMap.get(nodes[index])
< distanceMap.get(nodes[(index - 1) / 2])) {
swap(index, (index - 1) / 2);
index = (index - 1) / 2;
}
@ -115,7 +120,8 @@ public class Code06_Dijkstra {
int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left])
? left + 1
: left;
smallest = distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index;
smallest = distanceMap.get(nodes[smallest])
< distanceMap.get(nodes[index]) ? smallest : index;
if (smallest == index) {
break;
}

@ -0,0 +1,118 @@
package class10;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class Code07_MergeUsers {
public static class Node<V> {
V value;
public Node(V v) {
value = v;
}
}
public static class UnionSet<V> {
public HashMap<V, Node<V>> nodes;
public HashMap<Node<V>, Node<V>> parents;
public HashMap<Node<V>, Integer> sizeMap;
public UnionSet(List<V> values) {
for (V cur : values) {
Node<V> node = new Node<>(cur);
nodes.put(cur, node);
parents.put(node, node);
sizeMap.put(node, 1);
}
}
// 从点cur开始一直往上找找到不能再往上的代表点返回
public Node<V> findFather(Node<V> cur) {
Stack<Node<V>> path = new Stack<>();
while (cur != parents.get(cur)) {
path.push(cur);
cur = parents.get(cur);
}
// cur头节点
while (!path.isEmpty()) {
parents.put(path.pop(), cur);
}
return cur;
}
public boolean isSameSet(V a, V b) {
if (!nodes.containsKey(a) || !nodes.containsKey(b)) {
return false;
}
return findFather(nodes.get(a)) == findFather(nodes.get(b));
}
public void union(V a, V b) {
if (!nodes.containsKey(a) || !nodes.containsKey(b)) {
return;
}
Node<V> aHead = findFather(nodes.get(a));
Node<V> bHead = findFather(nodes.get(b));
if (aHead != bHead) {
int aSetSize = sizeMap.get(aHead);
int bSetSize = sizeMap.get(bHead);
Node<V> big = aSetSize >= bSetSize ? aHead : bHead;
Node<V> small = big == aHead ? bHead : aHead;
parents.put(small, big);
sizeMap.put(big, aSetSize + bSetSize);
sizeMap.remove(small);
}
}
public int getSetNum() {
return sizeMap.size();
}
}
public static class User {
public String a;
public String b;
public String c;
public User(String a, String b, String c) {
this.a = a;
this.b = b;
this.c = c;
}
}
// (1,10,13) (2,10,37) (400,500,37)
// 如果两个usera字段一样、或者b字段一样、或者c字段一样就认为是一个人
// 请合并users返回合并之后的用户数量
public static int mergeUsers(List<User> users) {
UnionSet<User> unionFind = new UnionSet<>(users);
HashMap<String, User> mapA = new HashMap<>();
HashMap<String, User> mapB = new HashMap<>();
HashMap<String, User> mapC = new HashMap<>();
for(User user : users) {
if(mapA.containsKey(user.a)) {
unionFind.union(user, mapA.get(user.a));
}else {
mapA.put(user.a, user);
}
if(mapB.containsKey(user.b)) {
unionFind.union(user, mapB.get(user.b));
}else {
mapB.put(user.b, user);
}
if(mapC.containsKey(user.c)) {
unionFind.union(user, mapC.get(user.c));
}else {
mapC.put(user.c, user);
}
}
// 向并查集询问,合并之后,还有多少个集合?
return unionFind.getSetNum();
}
}

@ -7,10 +7,11 @@ public class GraphGenerator {
// [weight, from节点上面的值to节点上面的值]
public static Graph createGraph(Integer[][] matrix) {
Graph graph = new Graph();
for (int i = 0; i < matrix.length; i++) { // matrix[0][0], matrix[0][1] matrix[0][2]
Integer from = matrix[i][0];
Integer to = matrix[i][1];
Integer weight = matrix[i][2];
for (int i = 0; i < matrix.length; i++) {
// matrix[0][0], matrix[0][1] matrix[0][2]
Integer weight = matrix[i][0];
Integer from = matrix[i][1];
Integer to = matrix[i][2];
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}

@ -2,6 +2,7 @@ package class10;
import java.util.ArrayList;
// 点结构的描述 A 0
public class Node {
public int value;
public int in;

@ -1,11 +1,14 @@
package class11;
import java.util.Stack;
public class Code01_Hanoi {
public static void hanoi1(int n) {
leftToRight(n);
}
// 请把1~N层圆盘 从左 -> 右
public static void leftToRight(int n) {
if (n == 1) {
System.out.println("Move 1 from left to right");
@ -16,6 +19,7 @@ public class Code01_Hanoi {
midToRight(n - 1);
}
// 请把1~N层圆盘 从左 -> 中
public static void leftToMid(int n) {
if (n == 1) {
System.out.println("Move 1 from left to mid");
@ -83,12 +87,54 @@ public class Code01_Hanoi {
}
}
public static class Record {
public boolean finish1;
public int base;
public String from;
public String to;
public String other;
public Record(boolean f1, int b, String f, String t, String o) {
finish1 = false;
base = b;
from = f;
to = t;
other = o;
}
}
public static void hanoi3(int N) {
if (N < 1) {
return;
}
Stack<Record> stack = new Stack<>();
stack.add(new Record(false, N, "left", "right", "mid"));
while (!stack.isEmpty()) {
Record cur = stack.pop();
if (cur.base == 1) {
System.out.println("Move 1 from " + cur.from + " to " + cur.to);
if (!stack.isEmpty()) {
stack.peek().finish1 = true;
}
} else {
if (!cur.finish1) {
stack.push(cur);
stack.push(new Record(false, cur.base - 1, cur.from, cur.other, cur.to));
} else {
System.out.println("Move " + cur.base + " from " + cur.from + " to " + cur.to);
stack.push(new Record(false, cur.base - 1, cur.other, cur.to, cur.from));
}
}
}
}
public static void main(String[] args) {
int n = 3;
hanoi1(n);
System.out.println("============");
hanoi2(n);
System.out.println("============");
hanoi3(n);
}
}

Loading…
Cancel
Save