modify code

master
algorithmzuo 2 years ago
parent b9a992340e
commit 7189c8d690

@ -0,0 +1,50 @@
package 03.mca_04;
// 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数
// 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外
// 其余每层节点数都达到最大值
// 并且最下面一层的节点都集中在该层最左边的若干位置
// 若最底层为第 h 层,则该层包含 1~ 2h 个节点。
// 测试链接 : https://leetcode.cn/problems/count-complete-tree-nodes/
public class Code01_CompleteTreeNodeNumber {
// 提交时不要提交这个类
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
}
// 提交如下的方法
public static int countNodes(TreeNode head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
// 当前来到node节点node节点在level层总层数是h
// 返回node为头的子树(必是完全二叉树),有多少个节点
public static int bs(TreeNode node, int Level, int h) {
if (Level == h) {
return 1;
}
if (mostLeftLevel(node.right, Level + 1) == h) {
return (1 << (h - Level)) + bs(node.right, Level + 1, h);
} else {
return (1 << (h - Level - 1)) + bs(node.left, Level + 1, h);
}
}
// 如果node在第level层
// 求以node为头的子树最大深度是多少
// node为头的子树一定是完全二叉树
public static int mostLeftLevel(TreeNode node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}
}

@ -0,0 +1,48 @@
package 03.mca_04;
// 给定一棵二叉树,你需要计算它的直径长度
// 一棵二叉树的直径长度是任意两个结点路径长度中的最大值
// 这条路径可能穿过也可能不穿过根结点
// 测试链接 : https://leetcode.cn/problems/diameter-of-binary-tree/
public class Code02_DiameterOfBinaryTree {
// 提交时不要提交这个类
public static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int value) {
val = value;
}
}
// 提交以下的方法
public static int diameterOfBinaryTree(TreeNode root) {
return process(root).maxDistance;
}
public static class Info {
public int maxDistance;
public int height;
public Info(int m, int h) {
maxDistance = m;
height = h;
}
}
public static Info process(TreeNode x) {
if (x == null) {
return new Info(0, 0);
}
Info leftInfo = process(x.left);
Info rightInfo = process(x.right);
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
int p1 = Math.max(leftInfo.maxDistance, rightInfo.maxDistance);
int p2 = leftInfo.height + rightInfo.height;
int maxDistance = Math.max(p1, p2);
return new Info(maxDistance, height);
}
}

@ -0,0 +1,87 @@
package 03.mca_04;
// 给定一个二叉树找到其中最大的二叉搜索树BST子树并返回该子树的大小
// 其中,最大指的是子树节点数最多的
// 二叉搜索树BST中的所有节点都具备以下属性
// 左子树的值小于其父(根)节点的值
// 右子树的值大于其父(根)节点的值
// 注意:子树必须包含其所有后代
// 测试链接 : https://leetcode.cn/problems/largest-bst-subtree
public class Code03_MaxSubBSTSize {
// 提交时不要提交这个类
public static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int value) {
val = value;
}
}
// 提交如下方法
public static int largestBSTSubtree(TreeNode head) {
if (head == null) {
return 0;
}
return process(head).maxBSTSubtreeSize;
}
public static class Info {
public int maxBSTSubtreeSize;
public int allSize;
public int max;
public int min;
public Info(int m, int a, int ma, int mi) {
maxBSTSubtreeSize = m;
allSize = a;
max = ma;
min = mi;
}
}
public static Info process(TreeNode x) {
if (x == null) {
return null;
}
Info leftInfo = process(x.left);
Info rightInfo = process(x.right);
int max = x.val;
int min = x.val;
int allSize = 1;
if (leftInfo != null) {
max = Math.max(leftInfo.max, max);
min = Math.min(leftInfo.min, min);
allSize += leftInfo.allSize;
}
if (rightInfo != null) {
max = Math.max(rightInfo.max, max);
min = Math.min(rightInfo.min, min);
allSize += rightInfo.allSize;
}
int p1 = -1;
if (leftInfo != null) {
p1 = leftInfo.maxBSTSubtreeSize;
}
int p2 = -1;
if (rightInfo != null) {
p2 = rightInfo.maxBSTSubtreeSize;
}
int p3 = -1;
boolean leftBST = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize);
boolean rightBST = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize);
if (leftBST && rightBST) {
boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.val);
boolean rightMinMoreX = rightInfo == null ? true : (x.val < rightInfo.min);
if (leftMaxLessX && rightMinMoreX) {
int leftSize = leftInfo == null ? 0 : leftInfo.allSize;
int rightSize = rightInfo == null ? 0 : rightInfo.allSize;
p3 = leftSize + rightSize + 1;
}
}
return new Info(Math.max(p1, Math.max(p2, p3)), allSize, max, min);
}
}

@ -0,0 +1,92 @@
package 03.mca_04;
// 测试链接 : https://www.nowcoder.com/questionTerminal/e7ed657974934a30b2010046536a5372
// 请务必理解这个文件的实现,而且还提供了测试链接
// 提交如下的code并把主类名改成"Main"
// 在测试链接里可以直接通过
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Code04_UnionFind {
public static int MAXN = 1000001;
public static int[] father = new int[MAXN];
public static int[] size = new int[MAXN];
public static int[] help = new int[MAXN];
// 初始化并查集
public static void init(int n) {
for (int i = 0; i <= n; i++) {
father[i] = i;
size[i] = 1;
}
}
// 从i开始寻找集合代表点
public static int find(int i) {
int hi = 0;
while (i != father[i]) {
help[hi++] = i;
i = father[i];
}
for (hi--; hi >= 0; hi--) {
father[help[hi]] = i;
}
return i;
}
// 查询x和y是不是一个集合
public static boolean isSameSet(int x, int y) {
return find(x) == find(y);
}
// x所在的集合和y所在的集合合并成一个集合
public static void union(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) {
if (size[fx] >= size[fy]) {
size[fx] += size[fy];
father[fy] = fx;
} else {
size[fy] += size[fx];
father[fx] = fy;
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) in.nval;
init(n);
in.nextToken();
int m = (int) in.nval;
for (int i = 0; i < m; i++) {
in.nextToken();
int op = (int) in.nval;
in.nextToken();
int x = (int) in.nval;
in.nextToken();
int y = (int) in.nval;
if (op == 1) {
out.println(isSameSet(x, y) ? "Yes" : "No");
out.flush();
} else {
union(x, y);
}
}
}
}
}

@ -0,0 +1,70 @@
package 03.mca_04;
// 本题为leetcode原题
// 测试链接https://leetcode.cn/problems/friend-circles/
// 可以直接通过
public class Code05_FriendCircles {
public static int findCircleNum(int[][] M) {
int N = M.length;
UnionFind uf = new UnionFind(N);
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (M[i][j] == 1) { // i和j互相认识
uf.union(i, j);
}
}
}
return uf.sets();
}
public static class UnionFind {
private int[] father;
private int[] size;
private int[] help;
private int sets;
public UnionFind(int N) {
father = new int[N];
size = new int[N];
help = new int[N];
sets = N;
for (int i = 0; i < N; i++) {
father[i] = i;
size[i] = 1;
}
}
private int find(int i) {
int hi = 0;
while (i != father[i]) {
help[hi++] = i;
i = father[i];
}
for (hi--; hi >= 0; hi--) {
father[help[hi]] = i;
}
return i;
}
public void union(int i, int j) {
int f1 = find(i);
int f2 = find(j);
if (f1 != f2) {
if (size[f1] >= size[f2]) {
size[f1] += size[f2];
father[f2] = f1;
} else {
size[f2] += size[f1];
father[f1] = f2;
}
sets--;
}
}
public int sets() {
return sets;
}
}
}

@ -0,0 +1,74 @@
package 03.mca_04;
// n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手
// 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的ID
// 情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1)
// 返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起
// 每次交换可选择任意两人,让他们站起来交换座位
// 测试链接 : https://leetcode.cn/problems/couples-holding-hands/
public class Code06_CouplesHoldingHands {
public int minSwapsCouples(int[] row) {
// n人数偶数
int n = row.length;
// n/2
// 0 1 -> 0 0
// 4 5 -> 2 2
UnionFind uf = new UnionFind(n / 2);
for (int i = 0; i < n; i += 2) {
uf.union(row[i] / 2, row[i + 1] / 2);
}
return n / 2 - uf.sets();
}
public static class UnionFind {
public int[] father;
public int[] size;
public int[] help;
public int sets;
public UnionFind(int n) {
father = new int[n];
size = new int[n];
help = new int[n];
for (int i = 0; i < n; i++) {
father[i] = i;
size[i] = 1;
}
sets = n;
}
private int find(int i) {
int hi = 0;
while (i != father[i]) {
help[hi++] = i;
i = father[i];
}
while (hi != 0) {
father[help[--hi]] = i;
}
return i;
}
public void union(int i, int j) {
int fi = find(i);
int fj = find(j);
if (fi != fj) {
if (size[fi] >= size[fj]) {
father[fj] = fi;
size[fi] += size[fj];
} else {
father[fi] = fj;
size[fj] += size[fi];
}
sets--;
}
}
public int sets() {
return sets;
}
}
}

@ -0,0 +1,155 @@
package 03.mca_04;
import java.util.Arrays;
import java.util.PriorityQueue;
// 在一个 n x n 的整数矩阵 grid 中,
// 每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。
// 当开始下雨时在时间为 t 水池中的水位为 t 
// 你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。
// 假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的。
// 当然,在你游泳的时候你必须待在坐标方格里面。
// 你从坐标方格的左上平台 (00) 出发。
// 返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间 。
// 测试链接 https://leetcode.cn/problems/swim-in-rising-water
public class Code07_SwimInRisingWater {
// 并查集的解法
public static int swimInWater1(int[][] grid) {
// 行号
int n = grid.length;
// 列号
int m = grid[0].length;
// [0,0,5]
// [0,1,3]....
int[][] points = new int[n * m][3];
int pi = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
points[pi][0] = i;
points[pi][1] = j;
points[pi++][2] = grid[i][j];
}
}
// 所有格子小对象,生成好了!
// 排序![a,b,c] [d,e,f]
Arrays.sort(points, (a, b) -> a[2] - b[2]);
// 生成并查集n * m
// 初始化的时候,把所有格子独自成一个集合!
UnionFind uf = new UnionFind(n, m);
int ans = 0;
for (int i = 0; i < points.length; i++) {
int r = points[i][0];
int c = points[i][1];
int v = points[i][2];
if (r > 0 && grid[r - 1][c] <= v) {
uf.union(r, c, r - 1, c);
}
if (r < n - 1 && grid[r + 1][c] <= v) {
uf.union(r, c, r + 1, c);
}
if (c > 0 && grid[r][c - 1] <= v) {
uf.union(r, c, r, c - 1);
}
if (c < m - 1 && grid[r][c + 1] <= v) {
uf.union(r, c, r, c + 1);
}
if (uf.isSameSet(0, 0, n - 1, m - 1)) {
ans = v;
break;
}
}
return ans;
}
public static class UnionFind {
public int col;
public int pointsSize;
public int[] father;
public int[] size;
public int[] help;
public UnionFind(int n, int m) {
col = m;
pointsSize = n * m;
father = new int[pointsSize];
size = new int[pointsSize];
help = new int[pointsSize];
for (int i = 0; i < pointsSize; i++) {
father[i] = i;
size[i] = 1;
}
}
private int find(int i) {
int hi = 0;
while (i != father[i]) {
help[hi++] = i;
i = father[i];
}
while (hi > 0) {
father[help[--hi]] = i;
}
return i;
}
private int index(int i, int j) {
return i * col + j;
}
public void union(int row1, int col1, int row2, int col2) {
int f1 = find(index(row1, col1));
int f2 = find(index(row2, col2));
if (f1 != f2) {
if (size[f1] >= size[f2]) {
father[f2] = f1;
size[f1] += size[f2];
} else {
father[f1] = f2;
size[f2] += size[f1];
}
}
}
public boolean isSameSet(int row1, int col1, int row2, int col2) {
return find(index(row1, col1)) == find(index(row2, col2));
}
}
// Dijkstra算法
public static int swimInWater2(int[][] grid) {
int n = grid.length;
int m = grid[0].length;
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[2] - b[2]);
boolean[][] visited = new boolean[n][m];
heap.add(new int[] { 0, 0, grid[0][0] });
int ans = 0;
while (!heap.isEmpty()) {
int r = heap.peek()[0];
int c = heap.peek()[1];
int v = heap.peek()[2];
heap.poll();
if (visited[r][c]) {
continue;
}
visited[r][c] = true;
if (r == n - 1 && c == m - 1) {
ans = v;
break;
}
add(grid, heap, visited, r - 1, c, v);
add(grid, heap, visited, r + 1, c, v);
add(grid, heap, visited, r, c - 1, v);
add(grid, heap, visited, r, c + 1, v);
}
return ans;
}
public static void add(int[][] grid, PriorityQueue<int[]> heap, boolean[][] visited, int r, int c, int preV) {
if (r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && !visited[r][c]) {
heap.add(new int[] { r, c, preV + Math.max(0, grid[r][c] - preV) });
}
}
}

@ -0,0 +1,122 @@
package 03.mca_04;
import java.util.HashMap;
// 本题测试链接 : https://leetcode.cn/problems/lru-cache/
public class Code08_LRUCache {
// 提交以下这个类
public class LRUCache {
public static class Node {
public int key;
public int val;
public Node last;
public Node next;
public Node(int k, int v) {
key = k;
val = v;
}
}
public static class DoubleLinkedList {
private Node head;
private Node tail;
public DoubleLinkedList() {
head = null;
tail = null;
}
public void addNode(Node newNode) {
if (newNode == null) {
return;
}
if (head == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
newNode.last = tail;
tail = newNode;
}
}
public void moveNodeToTail(Node node) {
if (tail == node) {
return;
}
if (head == node) {
head = node.next;
head.last = null;
} else {
node.last.next = node.next;
node.next.last = node.last;
}
node.last = tail;
node.next = null;
this.tail.next = node;
this.tail = node;
}
public Node removeHead() {
if (head == null) {
return null;
}
Node ans = this.head;
if (head == tail) {
head = null;
tail = null;
} else {
head = ans.next;
ans.next = null;
head.last = null;
}
return ans;
}
}
private HashMap<Integer, Node> keyNodeMap;
private DoubleLinkedList nodeList;
private final int capacity;
public LRUCache(int cap) {
keyNodeMap = new HashMap<>();
nodeList = new DoubleLinkedList();
capacity = cap;
}
public int get(int key) {
if (keyNodeMap.containsKey(key)) {
Node ans = keyNodeMap.get(key);
nodeList.moveNodeToTail(ans);
return ans.val;
}
return -1;
}
public void put(int key, int value) {
if (keyNodeMap.containsKey(key)) {
Node node = keyNodeMap.get(key);
node.val = value;
nodeList.moveNodeToTail(node);
} else {
Node newNode = new Node(key, value);
keyNodeMap.put(key, newNode);
nodeList.addNode(newNode);
if (keyNodeMap.size() == capacity + 1) {
removeMostUnusedCache();
}
}
}
private void removeMostUnusedCache() {
Node removeNode = nodeList.removeHead();
keyNodeMap.remove(removeNode.key);
}
}
}
Loading…
Cancel
Save