spring boot 健康检查 demo

This commit is contained in:
YunaiV
2019-09-11 19:12:29 +08:00
parent 31e607a6cf
commit 96db31ef99
42 changed files with 262 additions and 1339 deletions

View File

@@ -34,3 +34,7 @@
# lab-9
记录阅读极客时间《数据结构与算法之美》的题目。
# lab-10

View File

@@ -1,108 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0037;
@SuppressWarnings("Duplicates")
public class Solution01 {
public void solveSudoku(char[][] board) {
int n = 9;
int m = 3;
boolean[][] rows = new boolean[n][n];
boolean[][] cols = new boolean[n][n];
boolean[][] boxes = new boolean[n][n];
init(board, n, m,
rows, cols, boxes);
boolean result = solveSudoku(board, n, m, 0, 0,
rows, cols, boxes);
System.out.println(result);
}
private void init(char[][] board, int n, int m,
boolean[][] rows, boolean[][] cols, boolean[][] boxes) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == '.') {
continue;
}
int number = board[i][j] - '1'; // 减 1 而不是 0 ,因为数组从 0 开始。
// 行
rows[i][number] = true;
// 列
cols[j][number] = true;
// 小方格
int boxIndex = i / m * m + j / m;
boxes[boxIndex][number] = true;
}
}
}
private boolean solveSudoku(char[][] board, int n, int m, int i, int j,
boolean[][] rows, boolean[][] cols, boolean[][] boxes) {
if (i == n && j == 0) {
return true;
}
// 如果已经填写,判断有效性
if (board[i][j] != '.') {
// 递归
return solveSudoku(board, n, m, j + 1 == n ? i + 1 : i, j + 1 == n ? 0 : j + 1,
rows, cols, boxes);
}
// 如果未填写,就开始模拟填写
for (int number = 0; number < n; number++) {
// 行
if (rows[i][number]) {
continue;
}
// 列
if (cols[j][number]) {
continue;
}
// 小方格
int boxIndex = i / m * m + j / m;
if (boxes[boxIndex][number]) {
continue;
}
// 统一设置
rows[i][number] = true;
cols[j][number] = true;
boxes[boxIndex][number] = true;
board[i][j] = (char) (number + '1');
// 递归
boolean success = solveSudoku(board, n, m, j + 1 == n ? i + 1 : i, j + 1 == n ? 0 : j + 1,
rows, cols, boxes);
// 成功
if (success) {
return true;
}
// 失败
rows[i][number] = false;
cols[j][number] = false;
boxes[boxIndex][number] = false;
board[i][j] = '.';
}
// 如果一直失败,说明就是失败了
return false;
}
public static void main(String[] args) {
if (false) {
char[][] board = {{'.', '.', '.', '.', '5', '.', '.', '1', '.'}, {'.', '4', '.', '3', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '3', '.', '.', '1'}, {'8', '.', '.', '.', '.', '.', '.', '2', '.'}, {'.', '.', '2', '.', '7', '.', '.', '.', '.'}, {'.', '1', '5', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '2', '.', '.', '.'}, {'.', '2', '.', '9', '.', '.', '.', '.', '.'}, {'.', '.', '4', '.', '.', '.', '.', '.', '.'}};
// for (int i = 0; i < board.length; i++) {
// for (int j = 0; j < board[i].length; j++) {
// System.out.print(board[i][j] + "\t");
// }
// System.out.println();
// }
new Solution01().solveSudoku(board);
}
if (true) {
char[][] board = {{'5','3','.','.','7','.','.','.','.'},{'6','.','.','1','9','5','.','.','.'},{'.','9','8','.','.','.','.','6','.'},{'8','.','.','.','6','.','.','.','3'},{'4','.','.','8','.','3','.','.','1'},{'7','.','.','.','2','.','.','.','6'},{'.','6','.','.','.','.','2','8','.'},{'.','.','.','4','1','9','.','.','5'},{'.','.','.','.','8','.','.','7','9'}};
new Solution01().solveSudoku(board);
}
}
}

View File

@@ -1,10 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0069;
public class Main {
public static void main(String[] args) {
Solution02 solution = new Solution02();
System.out.println(solution.majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2}));
}
}

View File

@@ -1,18 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0069;
import java.util.Arrays;
/**
* TODO 题号不对。
*/
class Solution01 {
public int majorityElement(int[] nums) {
// 排序
Arrays.sort(nums);
// 因为超过 n/2 个,所以返回中间
return nums[nums.length / 2];
}
}

View File

@@ -1,39 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0069;
public class Solution02 {
public int majorityElement(int[] nums) {
return find(nums, 0, nums.length - 1);
}
private int find(int[] nums, int low, int high) {
if (low == high) {
return nums[low];
}
// 分治
int middle = (high - low) / 2 + low;
int left = find(nums, low, middle);
int right = find(nums, middle + 1, high);
// 判断两表结果是否相等
if (left == right) {
return left;
}
int leftCounts = count(nums, left, low, middle);
int rightCounts = count(nums, right, middle + 1, high);
return leftCounts > rightCounts ? left : right;
}
private int count(int[] nums, int target, int start, int end) {
int counts = 0;
for (int i = start; i <= end; i++) {
if (nums[i] == target) {
counts++;
}
}
return counts;
}
}

View File

@@ -1,26 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0070;
public class Solution {
public int climbStairs(int n) {
int f1 = 1; // 走一步
int f2 = 1; // 走两步
for (int i = 2; i <= n; i++) {
int fi = f1 + f2;
// 切换值
f1 = f2;
f2 = fi;
}
return f2;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.climbStairs(1));
System.out.println(solution.climbStairs(2));
System.out.println(solution.climbStairs(3));
System.out.println(solution.climbStairs(4));
System.out.println(solution.climbStairs(5));
}
}

View File

@@ -1,57 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0098;
public class Solution01 {
// 记录,遍历的前一个节点的值
private Integer last = null;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
// 左节点
if (root.left != null) {
boolean result = isValidBST(root.left);
if (!result) {
return false;
}
}
// root 当前
if (last != null && last >= root.val) {
return false;
}
last = root.val;
System.out.println(last);
// 右节点
if (root.right != null) {
return isValidBST(root.right);
}
return true;
}
public static void main(String[] args) {
// if (true) {
// Solution solution = new Solution();
// TreeNode root = new TreeNode(5);
// root.left = new TreeNode(1);
// root.right = new TreeNode(4);
// root.right.left = new TreeNode(3);
// root.right.right = new TreeNode(6);
// System.out.println(solution.isValidBST(root));
// }
if (true) {
Solution01 solution = new Solution01();
TreeNode root = new TreeNode(1);
root.left = new TreeNode(1);
// root.right = new TreeNode(4);
// root.right.left = new TreeNode(3);
// root.right.right = new TreeNode(6);
System.out.println(solution.isValidBST(root));
}
}
}

View File

@@ -1,47 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0098;
public class Solution02 {
public boolean isValidBST(TreeNode root) {
return isValid(root, null, null);
}
private boolean isValid(TreeNode node, Integer min, Integer max) {
// 节点为空,说明以它为基础的子树,是二叉搜索树
if (node == null) {
return true;
}
if (min != null && node.val <= min) {
return false;
}
if (max != null && node.val >= max) {
return false;
}
return isValid(node.left, min, node.val) // 左子树
&& isValid(node.right, node.val, max); // 右子树
}
public static void main(String[] args) {
// if (true) {
// Solution02 solution = new Solution02();
// TreeNode root = new TreeNode(5);
// root.left = new TreeNode(1);
// root.right = new TreeNode(4);
// root.right.left = new TreeNode(3);
// root.right.right = new TreeNode(6);
// System.out.println(solution.isValidBST(root));
// }
if (true) {
Solution02 solution = new Solution02();
TreeNode root = new TreeNode(1);
root.left = new TreeNode(1);
// root.right = new TreeNode(4);
// root.right.left = new TreeNode(3);
// root.right.right = new TreeNode(6);
System.out.println(solution.isValidBST(root));
}
}
}

View File

@@ -1,11 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0098;
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}

View File

@@ -1,34 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0121;
/**
* 贪心算法实现
*/
public class Solution02 {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int max = 0;
int buy = prices[0];
// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
// 计算,当前位置,卖出,能赚多少钱。
max = Math.max(max, prices[i] - buy);
// 计算当前位置值得买不
buy = Math.min(buy, prices[i]);
}
return max;
}
public static void main(String[] args) {
Solution02 solution = new Solution02();
System.out.println(solution.maxProfit(new int[]{7,1,5,3,6,4}));
System.out.println(solution.maxProfit(new int[]{7,1,5,3,6,4,7}));
System.out.println(solution.maxProfit(new int[]{7,6,4,3,1}));
}
}

View File

@@ -1,18 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0122;
/**
* 贪心算法实现
*/
public class Solution01 {
public int maxProfit(int[] prices) {
int result = 0;
for (int i = 0; i < prices.length - 1; i++) {
if (prices[i] < prices[i + 1]) {
result += prices[i + 1] - prices[i];
}
}
return result;
}
}

View File

@@ -1,33 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0122;
/**
* DP 算法实现
*/
public class Solution02 {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int zero = 0; // 无持有
int one = -prices[0]; // 持有股票
// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
// 尝试卖出
// if (one + (prices[i]) > zero) {
// zero = one + prices[i];
// }
zero = Math.max(zero, one + prices[i]); // 简化
// 尝试买入
// if (zero - prices[i] > one) {
// one = zero - prices[i];
// }
one = Math.max(one, zero - prices[i]); // 简化
}
return Math.max(one, zero);
}
}

View File

@@ -1,63 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0188;
/**
* TODO 需要优化,会超过。例如说 k = 10 亿
*/
public class Solution {
public int maxProfit(int k, int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
// 超过股票的一半,则只要买的有赚,就买入,第二天卖出。
if (k >= prices.length / 2) {
int result = 0;
for (int i = 0; i < prices.length - 1; i++) {
if (prices[i] < prices[i + 1]) {
result += prices[i + 1] - prices[i];
}
}
return result;
}
// 第一维度 k ,表示当前【买入股票】的次数;
// 第二维度 2 ,表示 0 - 未持有1 - 持有 1 股
// 值为最大利润
int[][] dp = new int[k + 1][2];
// 初始化第一个股票的处理
for (int i = 1; i <= k; i++) {
dp[i][1] = -prices[0]; // 买入
}
dp[0][1] = Integer.MIN_VALUE; // 相当于赋值为空,避免直接认为持有一股时,利润为 0 。
// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
for (int j = 0; j <= k; j++) {
// 尝试卖出
dp[j][0] = Math.max(dp[j][0], dp[j][1] + prices[i]);
// 尝试买入
if (j > 0) {
dp[j][1] = Math.max(dp[j][1], dp[j - 1][0] - prices[i]);
}
}
}
// 求最大值
int max = dp[0][0];
for (int i = 1; i <= k; i++) {
max = Math.max(max, dp[i][0]);
}
return max;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.maxProfit(2, new int[]{2, 4,1 }));
System.out.println(solution.maxProfit(7, new int[]{3,2,6,5,0,3}));
System.out.println(solution.maxProfit(2, new int[]{3,3,5,0,0,3,1,4}));
System.out.println(solution.maxProfit(2, new int[]{1,2,3,4,5}));
System.out.println(solution.maxProfit(2, new int[]{7, 6, 4, 3, 1}));
}
}

View File

@@ -1,28 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0191;
public class Solution01 {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int weight = 0;
// if (n < 0) {
// n = n - 1 + Integer.MAX_VALUE;
// }
// 计算有多少个 0
while (n != 0) {
n = n & (n - 1);
weight++;
}
return weight;
}
public static void main(String[] args) {
System.out.println(new Solution01().hammingWeight(Integer.MAX_VALUE));
System.out.println(new Solution01().hammingWeight(Integer.MIN_VALUE));
System.out.println(new Solution01().hammingWeight(-3));
}
}

View File

@@ -1,32 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0191;
/**
* 注意,这个做法,处理负数,会有问题。所以看 {@link Solution03}
*/
public class Solution02 {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int weight = 0;
// 计算有多少个 0
while (n != 0) {
if (n % 2 == 1) {
weight++;
// System.out.print(1);
} else {
// System.out.print(0);
}
n = n / 2;
}
return weight;
}
public static void main(String[] args) {
int n = 0b11111111000000001111111100000000;
System.out.println(new Solution02().hammingWeight(n));
// System.out.println(new Solution02().hammingWeight(-3));
}
}

View File

@@ -1,27 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0191;
public class Solution03 {
public int hammingWeight(int n) {
int mask = 1;
int weight = 0;
for (int i = 0; i < 32; i++) { // 32 的原因是int 是 32 位。
if ((n & mask) == mask) { // 其它位都被 & 掉后,直接等于 mask 了,如果当前位是 1 的话 ,或者换个写法 (n & mask) != 0
weight++;
}
mask = mask << 1; // 左移一位,准备和下一位对比
}
return weight;
}
public static void main(String[] args) {
// int n = 0b11111111000000001111111100000000;
// System.out.println(new Solution03().hammingWeight(n));
// System.out.println(new Solution03().hammingWeight(3));
// System.out.println(new Solution03().hammingWeight(-3));
System.out.println(new Solution03().hammingWeight(Integer.MIN_VALUE));
}
}

View File

@@ -1,134 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0200;
public class Solution {
public static class UnionFind {
/**
* 每个岛的节点的指向哪个岛
*/
private int[] roots;
/**
* 岛的数量
*/
private int count;
public UnionFind(char[][] grid) {
int n = grid.length;
int m = grid[0].length;
roots = new int[n * m];
// 初始,每个小岛都指向自己
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] != '1') {
continue;
}
roots[getIndex(grid, i, j)] = getIndex(grid, i, j);
count++;
}
}
}
public int findRoot(int i) {
int root = i;
// 寻找真正的 root
while (root != roots[root]) { // 自己指向自己的,才是真正的 root
root = roots[root];
}
// 路径压缩
while (i != root) { // 不断向上
int tmp = roots[i];
roots[i] = root;
i = tmp;
}
return root;
}
/**
* 将两个小岛进行合并
*
* @param p 岛 1
* @param q 岛 2
*/
public void union(int p, int q) {
int pRoot = findRoot(p);
int qRoot = findRoot(q);
// 如果 root 不同,则进行关联
if (pRoot != qRoot) {
roots[pRoot] = qRoot;
count--;
}
}
}
private static int[][] directions = {{1, 0}, {0, 1}};
private static boolean isValid(char[][] grid, int i, int j) {
return i >= 0 && i < grid.length
&& j >=0 && j < grid[i].length
&& grid[i][j] == '1';
}
private static int getIndex(char[][] grid, int i, int j) {
// int n = grid.length;
int m = grid[0].length;
return i * m + j;
}
public int numIslands(char[][] grid) {
if (grid.length == 0 || grid[0].length == 0) {
return 0;
}
// 创建并查级
UnionFind unionFind = new UnionFind(grid);
// 开始合并
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
// 非岛屿,跳过
if (!isValid(grid, i, j)) {
continue;
}
// 判断是否目标是岛屿
for (int[] direction : directions) {
// 非岛屿,跳过
if (!isValid(grid, i + direction[0], j + direction[1])) {
continue;
}
unionFind.union(getIndex(grid, i, j),
getIndex(grid, i + direction[0], j + direction[1]));
}
}
}
return unionFind.count;
}
public static void main(String[] args) {
Solution solution = new Solution();
// System.out.println(solution.numIslands(new char[][]{
// {'1', '1', '1', '1', '0'},
// {'1', '1', '0', '1', '0'},
// {'1', '1', '0', '0', '0'},
// {'0', '0', '0', '0', '0'},
// }));
// System.out.println(solution.numIslands(new char[][]{
// {'1', '1', '0', '0', '0'},
// {'1', '1', '0', '0', '0'},
// {'0', '0', '1', '0', '0'},
// {'0', '0', '0', '1', '1'},
// }));
System.out.println(solution.numIslands(new char[][]{
{'1'},
{'1'}
}));
}
}

View File

@@ -1,28 +0,0 @@
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
int n = M.size(), res = n;
vector<int> root(n);
for (int i = 0; i < n; ++i) root[i] = i;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (M[i][j] == 1) {
int p1 = getRoot(root, i);
int p2 = getRoot(root, j);
if (p1 != p2) {
--res;
root[p2] = p1;
}
}
}
}
return res;
}
int getRoot(vector<int>& root, int i) {
while (i != root[i]) {
root[i] = root[root[i]];
i = root[i];
}
return i;
}
};

View File

@@ -1,46 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0236;
public class Main {
public static void main(String[] args) {
if (false) {
TreeNode node3 = new TreeNode(3);
TreeNode node5 = new TreeNode(5);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);
TreeNode node4 = new TreeNode(4);
TreeNode node2 = new TreeNode(2);
TreeNode node1 = new TreeNode(1);
node3.left = node5;
node3.right = node1;
node5.left = node6;
node5.right = node2;
node6.left = node7;
node6.right = node4;
TreeNode result = new Solution01().lowestCommonAncestor(node3, node3, node5);
System.out.println(result.val);
}
if (true) {
TreeNode node3 = new TreeNode(3);
TreeNode node5 = new TreeNode(5);
TreeNode node1 = new TreeNode(1);
TreeNode node6 = new TreeNode(6);
TreeNode node2 = new TreeNode(2);
TreeNode node0 = new TreeNode(0);
TreeNode node8 = new TreeNode(8);
TreeNode node7 = new TreeNode(7);
TreeNode node4 = new TreeNode(4);
node3.left = node5;
node3.right = node1;
node5.left = node6;
node5.right = node2;
node1.left = node0;
node1.right = node8;
node2.left = node7;
node2.right = node4;
TreeNode result = new Solution01().lowestCommonAncestor(node3, node5, node4);
System.out.println(result.val);
}
}
}

View File

@@ -1,54 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0236;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class Solution01 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// p 节点的路径
List<TreeNode> pNodes = new ArrayList<>();
search(root, p, pNodes, new AtomicBoolean());
// q 节点的路径
List<TreeNode> qNodes = new ArrayList<>();
search(root, q, qNodes, new AtomicBoolean());
// 倒序,对比
for (int i = 0; i < pNodes.size(); i++) {
TreeNode node = pNodes.get(i);
for (int j = 0; j < qNodes.size(); j++) {
TreeNode node2 = qNodes.get(j);
if (node.val == node2.val) {
return node;
}
}
}
return null;
}
private void search(TreeNode root, TreeNode target, List<TreeNode> nodes, AtomicBoolean found) {
if (root == null) { // 理论不存在,防御性
return;
}
// 如果当前节点,就是要找的,就添加到 nodes 中
if (root.val == target.val) {
found.set(true);
nodes.add(root);
return;
}
// 如果不是,递归子节点
search(root.left, target, nodes, found);
if (!found.get()) {
search(root.right, target, nodes, found);
}
// 如果子节点找到,则添加到 nodes 中
if (found.get()) {
nodes.add(root);
}
}
}

View File

@@ -1,27 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0236;
public class Solution02 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 如果递归,当前节点 root 就是 p 或者 q ,则直接返回
if (root == null || root == p || root == q) {
return root;
}
// 遍历左子树
TreeNode left = lowestCommonAncestor(root.left, p, q);
// 遍历右子节点
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 上述,因为是先递归,后判断,所以一定会先招到最接近的。然后,就不断向上,返回最接近的了。
// 判断父节点
if (left == null) { // 左子树没找到,那就选择右子树。
return right;
}
if (right == null) { // 右子树没找到,那就选择左子树。
return left;
}
return root; // 如果左右子树都找到,说明 root 是它们的父节点
}
}

View File

@@ -1,11 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0236;
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}

View File

@@ -1,45 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0242;
import java.util.HashMap;
import java.util.Map;
class Solution {
public boolean isAnagram(String s, String t) {
if (s == null || t == null) {
return false;
}
if (s.length() != t.length()) {
return false;
}
// 创建 s 使用的哈希表
Map<Character, Integer> map = new HashMap<>();
for (char ch : s.toCharArray()) {
Integer counts = map.get(ch);
counts = counts != null ? counts + 1 : 1;
map.put(ch, counts);
}
// 判断 t 是否有
for (char ch : t.toCharArray()) {
Integer counts = map.get(ch);
if (counts == null) {
return false;
}
counts--;
if (counts == 0) {
map.remove(ch);
} else {
map.put(ch, counts);
}
}
return true;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.isAnagram("anagram", "nagaram"));
System.out.println(solution.isAnagram("rat", "cat"));
System.out.println(solution.isAnagram("ccac", "aacc"));
}
}

View File

@@ -1,50 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0322;
import java.util.Arrays;
public class Solution {
public int coinChange(int[] coins, int amount) {
int[] min = new int[amount + 1];
Arrays.fill(min, -1);
min[0] = 0;
for (int i = 0; i < coins.length; i++) {
int coin = coins[i];
if (coin > amount) {
continue;
}
min[coin] = 1;
}
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
int coin = coins[j];
int index = i - coin;
// 面额过大,大于 i 。
if (index < 0) {
continue;
}
// 如果为 -1 ,说明没有这个组合
if (min[index] == -1) {
continue;
}
if (min[i] == -1) {
min[i] = min[index] + 1;
} else {
min[i] = Math.min(min[i], min[index] + 1);
}
}
}
return min[amount];
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.coinChange(new int[]{1, 2, 5}, 11));
System.out.println(solution.coinChange(new int[]{1, 2, 5}, 11));
}
}

View File

@@ -1,35 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0322;
import java.util.Arrays;
public class Solution02 {
public int coinChange(int[] coins, int amount) {
int[] min = new int[amount + 1];
Arrays.fill(min, amount + 1); // 因为肯定不会使用到 amount + 1 个硬币。
min[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
int coin = coins[j];
int index = i - coin;
// 面额过大,大于 i 。
if (index < 0) {
continue;
}
// 如果为 -1 ,说明没有这个组合
min[i] = Math.min(min[i], min[index] + 1);
}
}
return min[amount] <= amount ? min[amount] : -1;
}
public static void main(String[] args) {
Solution02 solution = new Solution02();
System.out.println(solution.coinChange(new int[]{1, 2, 5}, 11));
System.out.println(solution.coinChange(new int[]{2}, 3));
}
}

View File

@@ -1,24 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0338;
import java.util.Arrays;
public class Solution01 {
public int[] countBits(int num) {
int[] results = new int[num + 1];
results[0] = 0;
// 计算每个位置的 bits 数量
for (int i = 1; i <= num; i++) {
int bits = i & 1; // 计算最后一位,是否为负数
results[i] = bits + results[i >> 1];
}
return results;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(new Solution01().countBits(5)));
}
}

View File

@@ -1,23 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0338;
import java.util.Arrays;
public class Solution02 {
public int[] countBits(int num) {
int[] results = new int[num + 1];
results[0] = 0;
// 计算每个位置的 bits 数量
for (int i = 1; i <= num; i++) {
results[i] = 1 + results[i & (i - 1)]; // 和 Solution01
}
return results;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(new Solution02().countBits(5)));
}
}

View File

@@ -1,104 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no039;
import java.util.*;
public class Solution {
class Node {
public int index;
public int value;
public Node(int index, int value) {
this.index = index;
this.value = value;
}
}
public int[] maxSlidingWindow(int[] nums, int k) {
List<Node> queue = new LinkedList<>();
List<Integer> result = new ArrayList<>(nums.length - k + 1);
for (int i = 0; i < nums.length; i++) {
int maxValue = Integer.MIN_VALUE;
if (!queue.isEmpty()) {
// 移除超过范围的节点
if (queue.get(0).index == i - k) {
queue.remove(0);
}
// 移除队列中,小于当前位置的元素
ListIterator<Node> listiterator = queue.listIterator(queue.size()); // 倒序向前
while (listiterator.hasPrevious()) {
Node node = listiterator.previous();
if (nums[i] >= node.value) {
listiterator.remove();
} else {
maxValue = node.value; // 说明,此值更大
}
}
}
// 判断是否有更大的
if (nums[i] > maxValue) {
maxValue = nums[i];
}
// 添加到队尾
queue.add(new Node(i, nums[i]));
// 添加到结果
if (i >= k -1) {
result.add(maxValue);
}
}
return result.stream().mapToInt(i -> i).toArray();
}
// public int[] maxSlidingWindow(int[] nums, int k) {
// int[] num = nums;
// int size = k;
// //num就是numssize就是kres一开始也可以用数组
// ArrayList<Integer> res = new ArrayList<>();
// if(num == null || num.length == 0 || size <= 0 || size > num.length){
// return res.stream().mapToInt(i -> i).toArray();
// }
// int left = 0, right = 0, max = num[0];
// while(right < num.length){
// while(right < num.length-1 && right - left < size-1){
// right++;
// if(num[right] > max){
// max = num[right];
// }
// }
// res.add(max);
// left++;
// if(right == num.length-1) break;
// if(num[left-1] == max){
// right = left;
// max = num[left];
// }
// }
// return res.stream().mapToInt(i -> i).toArray();
// }
public static void main(String[] args) {
if (false) {
int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
int k = 3;
int[] result = new Solution().maxSlidingWindow(nums, k);
System.out.println(Arrays.toString(result));
}
if (true) {
int[] nums = {1, 3, 1, 2, 0, 5};
int k = 3;
int[] result = new Solution().maxSlidingWindow(nums, k);
System.out.println(Arrays.toString(result));
}
}
// private static void println(List<Node> queue) {
// for (Node node : queue) {
// System.out.print(" " + node.value);
// }
// System.out.println();
// }
}

View File

@@ -1,76 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0547;
import java.util.HashSet;
import java.util.Set;
@Deprecated // 无法通过
public class Solution {
public int findCircleNum(int[][] M) {
int n = M.length;
if (n == 0) {
return 0;
}
// 初始化数据
int[] friends = new int[n];
for (int i = 0; i < n; i++) { // 自己指向自己
friends[i] = i;
}
// 重新梳理指向
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (M[i][j] == 1) {
if (friends[j] == j) {
friends[j] = friends[i];
} else {
// 向上设置其它节点,合并
int k = j;
while (true) {
int old = friends[k];
friends[k] = friends[i];
if (old == k) {
break;
}
k = old;
}
}
}
}
}
// 计算结果
Set<Integer> root = new HashSet<>();
for (int i = 0; i < n; i++) {
if (friends[i] != i) {
continue;
}
root.add(friends[i]);
}
return root.size();
}
public static void main(String[] args) {
Solution solution = new Solution();
// System.out.println(solution.findCircleNum(new int[][]{
// {1,1,0},
// {1,1,0},
// {0,0,1}
// }));
// System.out.println(solution.findCircleNum(new int[][]{
// {1,1,0},
// {1,1,1},
// {0,1,1}
// }));
// System.out.println(solution.findCircleNum(new int[][]{
// {1,0,0,1},
// {0,1,1,0},
// {0,1,1,1},
// {1,0,1,1}
// }));
// System.out.println(solution.findCircleNum(new int[][]{{1,0,0,0,0,0,0,0,0,1,0,0,0,0,0},{0,1,0,1,0,0,0,0,0,0,0,0,0,1,0},{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,1,0,1,0,0,0,1,0,0,0,1,0,0,0},{0,0,0,0,1,0,0,0,0,0,0,0,1,0,0},{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},{0,0,0,1,0,0,0,1,1,0,0,0,0,0,0},{0,0,0,0,0,0,0,1,1,0,0,0,0,0,0},{1,0,0,0,0,0,0,0,0,1,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,1,0,0,0,0},{0,0,0,1,0,0,0,0,0,0,0,1,0,0,0},{0,0,0,0,1,0,0,0,0,0,0,0,1,0,0},{0,1,0,0,0,0,0,0,0,0,0,0,0,1,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}));
System.out.println(solution.findCircleNum(new int[][]{{1,1,0,0,0,0,0,1,0,0,0,0,0,0,0},{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,1,0,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,1,0,0,0,0,1,1,0,0,0,0},{0,0,0,1,0,1,0,0,0,0,1,0,0,0,0},{0,0,0,1,0,0,1,0,1,0,0,0,0,1,0},{1,0,0,0,0,0,0,1,1,0,0,0,0,0,0},{0,0,0,0,0,0,1,1,1,0,0,0,0,1,0},{0,0,0,0,1,0,0,0,0,1,0,1,0,0,1},{0,0,0,0,1,1,0,0,0,0,1,1,0,0,0},{0,0,0,0,0,0,0,0,0,1,1,1,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0},{0,0,0,0,0,0,1,0,1,0,0,0,0,1,0},{0,0,0,0,0,0,0,0,0,1,0,0,0,0,1}}));
}
}

View File

@@ -1,131 +0,0 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0547;
@SuppressWarnings("Duplicates")
public class Solution02 {
public class UnionFind {
/**
* 指向
*/
private int[] roots;
/**
* 数量
*/
private int count;
public UnionFind(int[][] M) {
this.count = M.length;
this.roots = new int[count];
for (int i = 0; i < count; i++) {
roots[i] = i;
}
}
public int findRoot(int i) {
int root = i;
// 寻找真正的 root
while (roots[root] != root) {
root = roots[root];
}
// 如果自己不是 root ,需要将所有父节点,改成 root
while (i != root) {
int tmp = roots[i];
roots[i] = root;
i = tmp;
}
return root;
}
// 这个写法,是上面的写法的省略
// public int findRoot(int i) {
// // 路径压缩,并修改 i 为 root 。
// while (i != roots[i]) {
// roots[i] = roots[roots[i]];
// i = roots[i];
// }
//
// return i;
// }
public void union(int p, int q) {
int pRoot = findRoot(p);
int qRoot = findRoot(q);
if (pRoot != qRoot) {
roots[qRoot] = pRoot;
count--;
}
}
}
public int findCircleNum(int[][] M) {
int n = M.length;
if (n == 0) {
return 0;
}
UnionFind unionFind = new UnionFind(M);
// 重新梳理指向
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (M[i][j] == 1) {
unionFind.union(i, j);
}
}
}
// for (int i = 1; i < n; i++) {
// for (int j = 1; j < n; j++) {
// if (M[i][j] == 1) {
// unionFind.union(i, j);
// }
// }
// }
return unionFind.count;
}
public static void main(String[] args) {
Solution02 solution = new Solution02();
// System.out.println(solution.findCircleNum(new int[][]{
// {1,1,0},
// {1,1,0},
// {0,0,1}
// }));
// System.out.println(solution.findCircleNum(new int[][]{
// {1,1,0},
// {1,1,1},
// {0,1,1}
// }));
// System.out.println(solution.findCircleNum(new int[][]{
// {1,0,0,1},
// {0,1,1,0},
// {0,1,1,1},
// {1,0,1,1}
// }));
System.out.println(solution.findCircleNum(new int[][]{
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
}));
// System.out.println(solution.findCircleNum(new int[][]{
// {1,1,1,1, 1},
// {1,1,1,1, 1},
// {1,1,1,1, 1},
// {1,1,1,1, 1},
// {1,1,1,1, 1},
// }));
// System.out.println(solution.findCircleNum(new int[][]{{1,0,0,0,0,0,0,0,0,1,0,0,0,0,0},{0,1,0,1,0,0,0,0,0,0,0,0,0,1,0},{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,1,0,1,0,0,0,1,0,0,0,1,0,0,0},{0,0,0,0,1,0,0,0,0,0,0,0,1,0,0},{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},{0,0,0,1,0,0,0,1,1,0,0,0,0,0,0},{0,0,0,0,0,0,0,1,1,0,0,0,0,0,0},{1,0,0,0,0,0,0,0,0,1,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,1,0,0,0,0},{0,0,0,1,0,0,0,0,0,0,0,1,0,0,0},{0,0,0,0,1,0,0,0,0,0,0,0,1,0,0},{0,1,0,0,0,0,0,0,0,0,0,0,0,1,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}));
// System.out.println(solution.findCircleNum(new int[][]{{1,1,0,0,0,0,0,1,0,0,0,0,0,0,0},{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,1,0,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,1,0,0,0,0,1,1,0,0,0,0},{0,0,0,1,0,1,0,0,0,0,1,0,0,0,0},{0,0,0,1,0,0,1,0,1,0,0,0,0,1,0},{1,0,0,0,0,0,0,1,1,0,0,0,0,0,0},{0,0,0,0,0,0,1,1,1,0,0,0,0,1,0},{0,0,0,0,1,0,0,0,0,1,0,1,0,0,1},{0,0,0,0,1,1,0,0,0,0,1,1,0,0,0},{0,0,0,0,0,0,0,0,0,1,1,1,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0},{0,0,0,0,0,0,1,0,1,0,0,0,0,1,0},{0,0,0,0,0,0,0,0,0,1,0,0,0,0,1}}));
}
}

27
lab-10/pom.xml Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-10</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,22 @@
package cn.iocoder.springboot.labs.lab10;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@GetMapping("/hello")
public String hello() {
// System.out.println(Thread.currentThread().getName());
return "world";
}
@GetMapping("/sleep")
public String sleep() throws InterruptedException {
Thread.sleep(100L);
// System.out.println(Thread.currentThread().getName());
return "world";
}
}

View File

@@ -0,0 +1,13 @@
package cn.iocoder.springboot.labs.lab10;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringMVCApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMVCApplication.class);
}
}

View File

@@ -0,0 +1,15 @@
package cn.iocoder.springboot.labs.lab10;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class TestListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("事件:" + event);
}
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.springboot.labs.lab10;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
//@Component
public class UserHealthIndicator implements HealthIndicator {
/**
* user监控 访问: http://localhost:8088/health
*
* @return 自定义Health监控
*/
@Override
public Health health() {
return new Health.Builder().withDetail("usercount", 10) //自定义监控内容
.withDetail("userstatus", "up").down().build();
}
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.springboot.labs.lab10.lifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ServerLifeCycleConfiguration {
@Bean
public ServerLifeCycleHealthIndicator serverLifeCycleHealthIndicator() {
return new ServerLifeCycleHealthIndicator();
}
@Bean
public ServerLifeCycleListener serverLifeCycleListener() {
return new ServerLifeCycleListener(this.serverLifeCycleHealthIndicator());
}
}

View File

@@ -0,0 +1,8 @@
package cn.iocoder.springboot.labs.lab10.lifecycle;
// TODO sleep 时长的配置
public class ServerLifeCycleConfigurationProperties {
}

View File

@@ -0,0 +1,46 @@
package cn.iocoder.springboot.labs.lab10.lifecycle;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
public class ServerLifeCycleHealthIndicator extends AbstractHealthIndicator {
/**
* 服务状态
*
* 启动阶段:
* 1. 项目初始启动时,状态为 OUT_OF_SERVICE 不提供服务。
* 2. 服务启动完成ApplicationReadyEvent状态为 UP 启动。
* 3. 服务启动失败ApplicationFailedEvent状态 DOWN 关闭。
*
* 关闭阶段:
* 1. 服务开始关闭ContextClosedEvent状态为 OUT_OF_SERVICE 不提供服务。
* 2. 因为服务关闭完成,不存在事件,所以暂时不处理。
*
* 具体的状态变更,通过
*/
private volatile Status status = Status.OUT_OF_SERVICE;
@Override
protected void doHealthCheck(Health.Builder builder) {
builder.status(status);
}
public void up() {
this.status = Status.UP;
}
public void down() {
this.status = Status.DOWN;
}
public void outOfService() {
this.status = Status.OUT_OF_SERVICE;
}
public Status status() {
return this.status;
}
}

View File

@@ -0,0 +1,57 @@
package cn.iocoder.springboot.labs.lab10.lifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
public class ServerLifeCycleListener implements ApplicationListener<ApplicationEvent> {
private Logger logger = LoggerFactory.getLogger(getClass());
private ServerLifeCycleHealthIndicator healthIndicator;
public ServerLifeCycleListener(ServerLifeCycleHealthIndicator healthIndicator) {
this.healthIndicator = healthIndicator;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationReadyEvent) {
this.handleApplicationReadyEvent((ApplicationReadyEvent) event);
} else if (event instanceof ApplicationFailedEvent) {
this.handleApplicationFailedEvent((ApplicationFailedEvent) event);
} else if (event instanceof ContextClosedEvent) {
this.handleContextClosedEvent((ContextClosedEvent) event);
}
}
@SuppressWarnings("unused")
private void handleApplicationReadyEvent(ApplicationReadyEvent event) {
healthIndicator.up();
}
@SuppressWarnings("unused")
private void handleApplicationFailedEvent(ApplicationFailedEvent event) {
healthIndicator.down();
}
@SuppressWarnings("unused")
private void handleContextClosedEvent(ContextClosedEvent event) {
// 标记不提供服务
healthIndicator.outOfService();
// sleep 等待负载均衡完成健康检查
for (int i = 0; i < 20; i++) { // TODO 20 需要配置
logger.info("[handleContextClosedEvent][优雅关闭,第 {} sleep 等待负载均衡完成健康检查]", i);
try {
Thread.sleep(1000L);
} catch (InterruptedException ignore) {
}
}
}
}

View File

@@ -0,0 +1,28 @@
package cn.iocoder.springboot.labs.lab10.lifecycle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Status;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // TODO rest 没生效,得排查下。
@RequestMapping("/") // TODO 可配置
public class StatusController {
@Autowired
private ServerLifeCycleHealthIndicator serverLifeCycleHealthIndicator;
@RequestMapping("/status")
public ResponseEntity<String> status() {
Status status = serverLifeCycleHealthIndicator.status();
// 成功
if (Status.UP == status) {
return new ResponseEntity<>(status.getDescription(), HttpStatus.OK);
}
// 失败
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(status.getDescription());
}
}

View File

@@ -0,0 +1,2 @@
management.endpoint.health.show-details=always
server.port=9080

View File

@@ -18,6 +18,7 @@
<module>lab-07</module>
<module>lab-08</module>
<module>lab-09</module>
<module>lab-10</module>
</modules>