queue = new LinkedList<>();
48 | queue.add(root);
49 | while (!queue.isEmpty()) {
50 | TreeNode node = queue.poll();
51 | list.add(node.val);
52 | if (node.left != null) {
53 | queue.add(node.left);
54 | }
55 | if (node.right != null) {
56 | queue.add(node.right);
57 | }
58 | }
59 | int[] result = new int[list.size()];
60 | for (int i = 0; i < list.size(); i++) {
61 | result[i] = list.get(i);
62 | }
63 | return result;
64 | }
65 |
66 | public static void main(String[] args) {
67 | TreeNode pRoot1 = new TreeNode(1);
68 | TreeNode pNode11 = new TreeNode(2);
69 | TreeNode pRoot12 = new TreeNode(3);
70 | pRoot1.left = pNode11;
71 | pRoot1.right = pRoot12;
72 |
73 | TreeNode pNode21 = new TreeNode(4);
74 | TreeNode pRoot22 = new TreeNode(5);
75 | pNode11.left = pNode21;
76 | pNode11.right = pRoot22;
77 |
78 | TreeNode pNode23 = new TreeNode(6);
79 | TreeNode pRoot24 = new TreeNode(7);
80 | pRoot12.left = pNode23;
81 | pRoot12.right = pRoot24;
82 | System.out.println(pRoot1);
83 |
84 | int[] result = printTree(pRoot1);
85 | System.out.println(Arrays.toString(result));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question35/CopyComplexListNode.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question35;
2 |
3 | import org.w3c.dom.Node;
4 |
5 | /**
6 | * @Description: https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/
7 | * 剑指 Offer 35. 复杂链表的复制
8 | * @Author tinytongtong
9 | * @Date 2020/9/9 6:00 PM
10 | * @Version
11 | */
12 | public class CopyComplexListNode {
13 | private static class Node {
14 | int val;
15 | Node next;
16 | Node random;
17 |
18 | public Node(int val) {
19 | this.val = val;
20 | }
21 |
22 | @Override
23 | public String toString() {
24 | return "ComplexTreeNode{" +
25 | "val=" + val +
26 | ", next=" + next +
27 | '}';
28 | }
29 | }
30 |
31 | /**
32 | * 分三步:克隆、链接、删除原节点
33 | *
34 | * @param head
35 | * @return
36 | */
37 | private static Node cloneComplexNode(Node head) {
38 | if (head == null) {
39 | return null;
40 | }
41 | copyNode(head);
42 | linkNode(head);
43 | return reLinkNode(head);
44 | }
45 |
46 | private static void copyNode(Node head) {
47 | while (head != null) {
48 | Node node = new Node(head.val);
49 | node.next = head.next;
50 | head.next = node;
51 | head = node.next;
52 | }
53 | }
54 |
55 | private static void linkNode(Node head) {
56 | while (head != null) {
57 | Node node = head.next;
58 | if (head.random !=null) {
59 | node.random = head.random.next;
60 | }
61 | head = node.next;
62 | }
63 | }
64 |
65 | private static Node reLinkNode(Node head) {
66 | Node result = head.next;
67 | head = head.next;
68 | while (head != null && head.next !=null) {
69 | Node node = head.next;
70 | head.next = node.next;
71 | head = node.next;
72 | }
73 | return result;
74 | }
75 |
76 | public static void main(String[] args) {
77 | Node pRoot1 = new Node(7);
78 |
79 | Node pNode2 = new Node(13);
80 | pRoot1.next = pNode2;
81 |
82 | Node pNode3 = new Node(11);
83 | pNode2.next = pNode3;
84 |
85 | Node pNode4 = new Node(10);
86 | pNode3.next = pNode4;
87 |
88 | Node pNode5 = new Node(1);
89 | pNode4.next = pNode5;
90 |
91 | pNode2.random = pRoot1;
92 | pNode3.random = pNode5;
93 | pNode4.random = pNode3;
94 | pNode5.random = pRoot1;
95 |
96 | System.out.println(cloneComplexNode(pRoot1));
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question68/LowestCommonAncestorBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question68;
2 |
3 | /**
4 | * @Description: https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/
5 | * 剑指 Offer 68 - II. 二叉树的最近公共祖先
6 | * @Author tinytongtong
7 | * @Date 2020/10/20 1:47 PM
8 | * @Version
9 | */
10 | public class LowestCommonAncestorBinaryTree {
11 | private static class TreeNode {
12 | int val;
13 | TreeNode left;
14 | TreeNode right;
15 |
16 | public TreeNode(int val) {
17 | this.val = val;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "TreeNode{" +
23 | "val=" + val +
24 | ", left=" + left +
25 | ", right=" + right +
26 | '}';
27 | }
28 | }
29 |
30 | /**
31 | * 递归解法
32 | * https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-er-cha-shu-de-zui-jin-gong-gon-7/
33 | *
34 | * @param root
35 | * @param p
36 | * @param q
37 | * @return
38 | */
39 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
40 | if(root == null || root.val == p.val || root.val == q.val) return root;
41 | TreeNode left = lowestCommonAncestor(root.left, p, q);
42 | TreeNode right = lowestCommonAncestor(root.right, p, q);
43 | if(left == null) return right;
44 | if(right == null) return left;
45 | return root;
46 | }
47 |
48 | public static void main(String[] args) {
49 | LowestCommonAncestorBinaryTree lca = new LowestCommonAncestorBinaryTree();
50 | TreeNode root = new TreeNode(3);
51 | TreeNode node11 = new TreeNode(5);
52 | TreeNode node12 = new TreeNode(1);
53 | root.left = node11;
54 | root.right = node12;
55 |
56 | TreeNode node21 = new TreeNode(6);
57 | TreeNode node22 = new TreeNode(2);
58 | node11.left = node21;
59 | node11.right = node22;
60 |
61 | TreeNode node23 = new TreeNode(0);
62 | TreeNode node24 = new TreeNode(8);
63 | node12.left = node23;
64 | node12.right = node24;
65 |
66 | TreeNode node31 = new TreeNode(7);
67 | TreeNode node32 = new TreeNode(4);
68 | node22.left = node31;
69 | node22.right = node32;
70 |
71 | TreeNode p = new TreeNode(5);
72 | TreeNode q = new TreeNode(1);
73 | System.out.println(root);
74 | TreeNode result = lca.lowestCommonAncestor(root, p, q);
75 | System.out.println(result != null ? result.toString() : "null");
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/question/question_0629/InversePairs.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.question.question_0629;
2 |
3 | /**
4 | * @Description: 629. K个逆序对数组
5 | * 逆序对
6 | * 剑指Offer第36题
7 | * LeetCode第629题
8 | * https://leetcode-cn.com/problems/k-inverse-pairs-array/
9 | * @Author tinytongtong
10 | * @Date 2020-02-06 16:06
11 | * @Version
12 | */
13 | public class InversePairs {
14 | public static int inversePairs(int[] data, int length) {
15 | if (data == null || length < 0) {
16 | return 0;
17 | }
18 |
19 | int[] copy = new int[length];
20 | for (int i = 0; i < length; i++) {
21 | copy[i] = data[i];
22 | }
23 |
24 | int count = inversesPairsCore(data, copy, 0, length - 1);
25 | return count;
26 | }
27 |
28 | /**
29 | * 递归调用的方法
30 | * 返回start-end之间数据的逆序对
31 | * 先进行升序排序,再进行比对
32 | *
33 | * @param data 原数据
34 | * @param copy 辅助数组,用来承装排好序的数据
35 | * @param start 起始角标
36 | * @param end 结束角标
37 | * @return
38 | */
39 | public static int inversesPairsCore(int[] data, int[] copy, int start, int end) {
40 | if (start == end) {
41 | copy[start] = data[start];
42 | return 0;
43 | }
44 |
45 | // 将数组分为两部分,这个是第一部分的长度
46 | int length = (end - start) / 2;
47 |
48 | // 获取左右子数组的逆序对数,递归调用
49 | // 这里需要格外注意,依次传入的是copy和data,不是data和copy
50 | int left = inversesPairsCore(copy, data, start, start + length);
51 | int right = inversesPairsCore(copy, data, start + length + 1, end);
52 |
53 | // i初始化为前半段最后一个数字的下标
54 | int i = start + length;
55 | // j初始化为后半段最后一个数字的下标
56 | int j = end;
57 | // 辅助数组从右向左复制,这个是起点
58 | int indexCopy = end;
59 | // 左右数组之间的的逆序对数
60 | int count = 0;
61 | // 开始复制
62 | while (i >= start && j >= start + length + 1) {
63 | if (data[i] > data[j]) {
64 | copy[indexCopy--] = data[i--];
65 | // 右侧数组当前的数字全部小于左侧的数字,所以都是逆序对
66 | count += j - start - length;
67 | } else {
68 | copy[indexCopy--] = data[j--];
69 | }
70 | }
71 |
72 | // 将剩下的数据copy进辅助数组
73 | for (; i >= start; --i) {
74 | copy[indexCopy--] = data[i];
75 | }
76 |
77 | for (; j >= start + length + 1; --j) {
78 | copy[indexCopy--] = data[j];
79 | }
80 |
81 | return left + right + count;
82 | }
83 |
84 | public static void main(String[] args) {
85 | int[] data = new int[]{7, 5, 6, 4};
86 | int count = inversePairs(data, data.length);
87 | System.out.println("count:" + count);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question12/MatrixHasPath.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question12;
2 |
3 | /**
4 | * @Description: https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
5 | * 剑指 Offer 12. 矩阵中的路径
6 | * @Author tinytongtong
7 | * @Date 2020/9/5 9:44 PM
8 | * @Version
9 | */
10 | public class MatrixHasPath {
11 | private static boolean hasPath(char[][] matrix, String str) {
12 | if (matrix == null || matrix.length < 1 || matrix[0].length < 1 || str == null) {
13 | return false;
14 | }
15 | int rows = matrix.length;
16 | int cols = matrix[0].length;
17 | boolean[][] visited = new boolean[rows][cols];
18 | int[] pathLength = new int[1];
19 | for (int i = 0; i < rows; i++) {
20 | for (int j = 0; j < cols; j++) {
21 | if (hasPathCore(matrix, i, j, str, pathLength, visited)) {
22 | return true;
23 | }
24 | }
25 | }
26 | return false;
27 | }
28 |
29 | private static boolean hasPathCore(char[][] matrix, int row, int col, String str, int[] pathLength, boolean[][] visited) {
30 | if (pathLength[0] == str.length()) {
31 | return true;
32 | }
33 | int rows = matrix.length;
34 | int cols = matrix[0].length;
35 | boolean hasPath = false;
36 | if (row >= 0 && row < rows && col >= 0 && col < cols && matrix[row][col] == str.charAt(pathLength[0]) && !visited[row][col]) {
37 | pathLength[0]++;
38 | visited[row][col] = true;
39 | hasPath = hasPathCore(matrix, row, col - 1, str, pathLength, visited)
40 | || hasPathCore(matrix, row - 1, col, str, pathLength, visited)
41 | || hasPathCore(matrix, row, col + 1, str, pathLength, visited)
42 | || hasPathCore(matrix, row + 1, col, str, pathLength, visited);
43 | if (!hasPath) {
44 | --pathLength[0];
45 | visited[row][col] = false;
46 | }
47 | }
48 | return hasPath;
49 | }
50 |
51 | public static void main(String[] args) {
52 | char[][] matrix = new char[][]{
53 | {'A', 'B', 'C', 'E'},
54 | {'S', 'F', 'C', 'S'},
55 | {'A', 'D', 'E', 'E'}
56 | };
57 | String str = "ABCCED";
58 | boolean result = hasPath(matrix, str);
59 | System.out.println(result);
60 |
61 | char[][] matrix1 = new char[][]{
62 | {'a', 'b'},
63 | {'c', 'd'}
64 | };
65 | String str1 = "ABCCED";
66 | boolean result1 = hasPath(matrix1, str1);
67 | System.out.println(result1);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question47/MaxValueOfGift.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question47;
2 |
3 | /**
4 | * @Description: https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/
5 | * 剑指 Offer 47. 礼物的最大价值
6 | * @Author tinytongtong
7 | * @Date 2020/9/13 10:38 AM
8 | * @Version
9 | */
10 | public class MaxValueOfGift {
11 | /**
12 | * 迭代解法:需要同等大小的辅助数组
13 | * 时间复杂度O(mn)
14 | * 空间复杂度O(mn)
15 | *
16 | * @param grid
17 | * @return
18 | */
19 | private static int maxValue(int[][] grid) {
20 | if (grid == null || grid.length == 0 || grid[0].length == 0) {
21 | return 0;
22 | }
23 | int rows = grid.length;
24 | int columns = grid[0].length;
25 | int[][] values = new int[rows][columns];
26 | for (int i = 0; i < rows; i++) {
27 | for (int j = 0; j < columns; j++) {
28 | int up = 0;
29 | int left = 0;
30 | if (i > 0) {
31 | up = values[i - 1][j];
32 | }
33 | if (j > 0) {
34 | left = values[i][j - 1];
35 | }
36 | int max = up > left ? up : left;
37 | values[i][j] = grid[i][j] + max;
38 | }
39 | }
40 | return values[rows - 1][columns - 1];
41 | }
42 |
43 | /**
44 | * 迭代解法:需要一个大小为列数的一维数组
45 | * 时间复杂度O(mn)
46 | * 空间复杂度O(n)
47 | *
48 | * @param grid
49 | * @return
50 | */
51 | private static int maxValue1(int[][] grid) {
52 | if (grid == null || grid.length == 0 || grid[0].length == 0) {
53 | return 0;
54 | }
55 | int rows = grid.length;
56 | int columns = grid[0].length;
57 | int[] values = new int[columns];
58 | for (int i = 0; i < rows; i++) {
59 | for (int j = 0; j < columns; j++) {
60 | int up = 0;
61 | int left = 0;
62 | if (i > 0) {
63 | up = values[j];
64 | }
65 | if (j > 0) {
66 | left = values[j - 1];
67 | }
68 | int max = up > left ? up : left;
69 | values[j] = grid[i][j] + max;
70 | }
71 | }
72 | return values[columns - 1];
73 | }
74 |
75 | public static void main(String[] args) {
76 | int[][] grid = new int[][]{
77 | {1, 10, 3, 8},
78 | {12, 2, 9, 6},
79 | {5, 7, 4, 11},
80 | {3, 7, 16, 5}
81 | };
82 | int result = maxValue(grid);
83 | System.out.println(result);
84 | System.out.println(maxValue1(grid));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question49/UglyNumber.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question49;
2 |
3 | /**
4 | * @Description: https://leetcode-cn.com/problems/chou-shu-lcof/
5 | * 剑指 Offer 49. 丑数
6 | * @Author tinytongtong
7 | * @Date 2020/9/13 9:07 PM
8 | * @Version
9 | */
10 | public class UglyNumber {
11 | /**
12 | * 暴力解法
13 | * @param n
14 | * @return
15 | */
16 | private static int nthUglyNumber(int n) {
17 | if (n <= 0) {
18 | return 0;
19 | }
20 | int number = 0;
21 | int uglyFound = 0;
22 | while (uglyFound < n) {
23 | ++number;
24 | if (isUgly(number)) {
25 | uglyFound++;
26 | }
27 | }
28 | return number;
29 | }
30 |
31 | /**
32 | * @param number
33 | * @return
34 | */
35 | private static boolean isUgly(int number) {
36 | while (number % 2 == 0) {
37 | number /= 2;
38 | }
39 | while (number % 3 == 0) {
40 | number /= 3;
41 | }
42 | while (number % 5 == 0) {
43 | number /= 5;
44 | }
45 | return number == 1;
46 | }
47 |
48 | /**
49 | * 只找丑数
50 | * @param n
51 | * @return
52 | */
53 | private static int nthUglyNumber1(int n) {
54 | if (n <= 0) {
55 | return 0;
56 | }
57 | int[] uglyNumbers = new int[n];
58 | uglyNumbers[0] = 1;
59 | int nextUglyIndex = 1;
60 | int[] multiply2 = uglyNumbers;
61 | int index2 = 0;
62 | int[] multiply3 = uglyNumbers;
63 | int index3 = 0;
64 | int[] multiply5 = uglyNumbers;
65 | int index5 = 0;
66 |
67 | while (nextUglyIndex < n) {
68 | int min = min(multiply2[index2] * 2, multiply3[index3] * 3, multiply5[index5] * 5);
69 | uglyNumbers[nextUglyIndex] = min;
70 | while (multiply2[index2] * 2 <= uglyNumbers[nextUglyIndex]) {
71 | index2++;
72 | }
73 | while (multiply3[index3] * 3 <= uglyNumbers[nextUglyIndex]) {
74 | index3++;
75 | }
76 | while (multiply5[index5] * 5 <= uglyNumbers[nextUglyIndex]) {
77 | index5++;
78 | }
79 | nextUglyIndex++;
80 | }
81 |
82 | int number = uglyNumbers[nextUglyIndex - 1];
83 | return number;
84 | }
85 |
86 | private static int min(int number2, int number3, int number5) {
87 | int min = number2 < number3 ? number2 : number3;
88 | min = min < number5 ? min : number5;
89 | return min;
90 | }
91 |
92 |
93 | public static void main(String[] args) {
94 | System.out.println(nthUglyNumber(7));
95 | System.out.println(nthUglyNumber1(8));
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/question/question_0104/MaximumDepthOfBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.question.question_0104;
2 |
3 | import java.util.LinkedList;
4 | import java.util.Queue;
5 |
6 | /**
7 | * @Description: https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
8 | * 104. 二叉树的最大深度
9 | * @Author tinytongtong
10 | * @Date 2020/9/2 11:36 AM
11 | * @Version
12 | */
13 | public class MaximumDepthOfBinaryTree {
14 |
15 | private static class TreeNode {
16 | int val;
17 | TreeNode left;
18 | TreeNode right;
19 |
20 | public TreeNode(int val) {
21 | this.val = val;
22 | }
23 | }
24 |
25 | /**
26 | * 递归 DFS
27 | * 时间复杂度:O(n),其中 nn 为二叉树节点的个数。每个节点在递归中只被遍历一次。
28 | * 空间复杂度:O(height),其中 height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。
29 | *
30 | * 作者:LeetCode-Solution
31 | * 链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/er-cha-shu-de-zui-da-shen-du-by-leetcode-solution/
32 | * 来源:力扣(LeetCode)
33 | * 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
34 | *
35 | * @param root
36 | * @return
37 | */
38 | private static int maxDepth(TreeNode root) {
39 | if (root == null) {
40 | return 0;
41 | }
42 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
43 | }
44 |
45 | /**
46 | * 迭代 BFS
47 | *
48 | * @param root
49 | * @return
50 | */
51 | private static int maxDepthBFS(TreeNode root) {
52 | if (root == null) {
53 | return 0;
54 | }
55 | Queue queue = new LinkedList<>();
56 | queue.offer(root);
57 | int result = 0;
58 | // 循环拿出本层所有的节点
59 | while (!queue.isEmpty()) {
60 | // 把每层所有节点都加入到队列中
61 | int size = queue.size();
62 | while (size > 0) {
63 | TreeNode node = queue.poll();
64 | if (node.left != null) {
65 | queue.offer(node.left);
66 | }
67 | if (node.right != null) {
68 | queue.offer(node.right);
69 | }
70 | size--;
71 | }
72 | result++;
73 | }
74 | return result;
75 | }
76 |
77 | public static void main(String[] args) {
78 | TreeNode root = new TreeNode(3);
79 | TreeNode node11 = new TreeNode(9);
80 | root.left = node11;
81 | TreeNode node12 = new TreeNode(20);
82 | root.right = node12;
83 | TreeNode node21 = new TreeNode(15);
84 | TreeNode node22 = new TreeNode(7);
85 | node12.left = node21;
86 | node12.right = node22;
87 |
88 | int result = maxDepth(root);
89 | System.out.println(result);
90 |
91 | int result1 = maxDepthBFS(root);
92 | System.out.println(result1);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question59/MaxSlidingWindow.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question59;
2 |
3 | import java.util.ArrayDeque;
4 | import java.util.Arrays;
5 | import java.util.Deque;
6 | import java.util.LinkedList;
7 |
8 | /**
9 | * @Description: https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
10 | * 剑指 Offer 59 - I. 滑动窗口的最大值
11 | * @Author tinytongtong
12 | * @Date 2020/9/17 9:40 AM
13 | * @Version
14 | */
15 | public class MaxSlidingWindow {
16 |
17 | private static int[] maxSlidingWindow(int[] nums, int k) {
18 | if (nums == null || nums.length <= 0 || k > nums.length) {
19 | return new int[0];
20 | }
21 | int[] result = new int[nums.length - k + 1];
22 | Deque deque = new ArrayDeque<>();
23 | // 获取前k个数的最大值。
24 | for (int i = 0; i < k; i++) {
25 | while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
26 | deque.pollLast();
27 | }
28 | deque.addLast(i);
29 | }
30 | // 移动窗口,获取最大值
31 | for (int i = k; i < nums.length; i++) {
32 | result[i - k] = nums[deque.peekFirst()];
33 | while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
34 | deque.pollLast();
35 | }
36 | if (!deque.isEmpty() && deque.peekFirst() <= (i - k)) {
37 | deque.pollFirst();
38 | }
39 | deque.addLast(i);
40 | }
41 | result[result.length - 1] = nums[deque.peekFirst()];
42 | return result;
43 | }
44 |
45 | private static int[] maxSlidingWindow1(int[] nums, int k) {
46 | // 异常数据校验
47 | if (nums == null || nums.length <= 0 || k > nums.length) {
48 | return new int[0];
49 | }
50 |
51 | int[] result = new int[nums.length - k + 1];
52 | Deque deque = new LinkedList<>();
53 | // m表示窗口的起点,n表示当前的元素角标
54 | // m大于等于0,表示窗口的数据满了,符合移动的条件了
55 | for (int m = 1 - k, n = 0; n < nums.length; m++, n++) {
56 | // 先删除超出窗口边界的元素。m=0表示第一个窗口,m>0表示移动后的窗口。
57 | if (m > 0 && deque.peekFirst() == nums[m - 1]) {
58 | deque.removeFirst();
59 | }
60 | // 比较新加入的元素跟现有元素的大小,保证最大值在左侧,同时要保证队列递减
61 | while (!deque.isEmpty() && deque.peekLast() < nums[n]) {
62 | deque.removeLast();
63 | }
64 | deque.addLast(nums[n]);
65 | if (m >= 0) {
66 | result[m] = deque.peekFirst();
67 | }
68 | }
69 | return result;
70 | }
71 |
72 | public static void main(String[] args) {
73 | int[] nums = new int[]{2, 3, 4, 2, 6, 2, 5, 1};
74 | System.out.println(Arrays.toString(maxSlidingWindow(nums, 3)));
75 | System.out.println(Arrays.toString(maxSlidingWindow1(nums, 3)));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question23/MeetingNodeInCycle.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question23;
2 |
3 |
4 | /**
5 | * @Description: 剑指 Offer 23. 链表中环的入口节点
6 | * @Author tinytongtong
7 | * @Date 2020/9/8 9:20 AM
8 | * @Version
9 | */
10 | public class MeetingNodeInCycle {
11 | private static class ListNode {
12 | int val;
13 | ListNode next;
14 |
15 | public ListNode(int val) {
16 | this.val = val;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return "ListNode{" +
22 | "val=" + val +
23 | '}';
24 | }
25 | }
26 |
27 | /**
28 | * 第一步确定是否有环
29 | * 快慢指针,找到环中任意一个节点
30 | *
31 | * @param head
32 | * @return
33 | */
34 | private static ListNode meetingNode(ListNode head) {
35 | if (head == null) {
36 | return null;
37 | }
38 | ListNode result = null;
39 | ListNode pFast = head;
40 | ListNode pSlow = head;
41 | while (pFast.next != null && pFast.next.next != null) {
42 | pFast = pFast.next.next;
43 | pSlow = pSlow.next;
44 | if (pFast.val == pSlow.val) {
45 | result = pFast;
46 | break;
47 | }
48 | }
49 | return result;
50 | }
51 |
52 | /**
53 | * 第二步找到环的入口
54 | *
55 | * @param pHead
56 | * @return
57 | */
58 | private static ListNode entryNodeOfLoop(ListNode pHead) {
59 | ListNode pMeeting = meetingNode(pHead);
60 | if (pMeeting == null) {
61 | return null;
62 | }
63 | // 先得到环节点的数目
64 | int count = 1;
65 | ListNode pNode = pMeeting.next;
66 | while (pNode.val != pMeeting.val) {
67 | pNode = pNode.next;
68 | count++;
69 | }
70 | ListNode pFast = pHead;
71 | ListNode pSlow = pHead;
72 | // 快慢指针,找到入口节点
73 | while (count > 0) {
74 | pFast = pFast.next;
75 | count--;
76 | }
77 | while (pFast.val != pSlow.val) {
78 | pFast = pFast.next;
79 | pSlow = pSlow.next;
80 | }
81 | return pFast;
82 | }
83 |
84 | public static void main(String[] args) {
85 | ListNode pHead = new ListNode(1);
86 | ListNode pNode2 = new ListNode(2);
87 | ListNode pNode3 = new ListNode(3);
88 | ListNode pNode4 = new ListNode(4);
89 | ListNode pNode5 = new ListNode(5);
90 | pHead.next = pNode2;
91 | pNode2.next = pNode3;
92 | pNode3.next = pNode4;
93 | pNode4.next = pNode5;
94 | pNode5.next = pNode4;
95 | System.out.println(pHead);
96 |
97 | System.out.println(entryNodeOfLoop(pHead));
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question38/NQueen.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question38;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | /**
8 | * @Description: https://leetcode-cn.com/problems/eight-queens-lcci/
9 | * n皇后问题
10 | * @Author tinytongtong
11 | * @Date 2020/9/10 6:03 PM
12 | * @Version
13 | */
14 | public class NQueen {
15 | private static List> solveNQueens(int n) {
16 | List> result = new ArrayList<>();
17 | if (n <= 0) return result;
18 | // 得到全排列
19 | int[] nums = new int[n];
20 | for (int i = 0; i < n; i++) {
21 | nums[i] = i;
22 | }
23 | List list = new ArrayList<>();
24 | permutationCore(nums, list, 0);
25 | // 挑选符合规则的数组
26 | List queenList = new ArrayList<>();
27 | for (int[] item : list) {
28 | if (verifyQueen(item)) queenList.add(item);
29 | }
30 | // 将数组转换成Q字符串
31 | for (int[] item : queenList) {
32 | result.add(convertToQueen(item));
33 | }
34 | return result;
35 | }
36 |
37 | private static void permutationCore(int[] nums, List list, int start) {
38 | if (start == nums.length) {
39 | list.add(Arrays.copyOf(nums, nums.length));
40 | } else {
41 | for (int i = start; i < nums.length; i++) {
42 | swap(nums, i, start);
43 | permutationCore(nums, list, start + 1);
44 | swap(nums, i, start);
45 | }
46 | }
47 | }
48 |
49 | private static boolean verifyQueen(int[] nums) {
50 | for (int i = 0; i < nums.length; i++) {
51 | for (int j = 0; j < nums.length; j++) {
52 | if (i != j) {
53 | if (j - i == nums[j] - nums[i] || i - j == nums[j] - nums[i]) return false;
54 | }
55 | }
56 | }
57 | return true;
58 | }
59 |
60 | private static void swap(int[] nums, int index1, int index2) {
61 | int temp = nums[index1];
62 | nums[index1] = nums[index2];
63 | nums[index2] = temp;
64 | }
65 |
66 | private static List convertToQueen(int[] nums) {
67 | List strList = new ArrayList<>();
68 | for (int i = 0; i < nums.length; i++) {
69 | StringBuilder sb = new StringBuilder();
70 | for (int j = 0; j < nums.length; j++) {
71 | if (nums[i] == j) {
72 | sb.append("Q");
73 | } else {
74 | sb.append(".");
75 | }
76 | }
77 | strList.add(sb.toString());
78 | }
79 | return strList;
80 | }
81 |
82 | public static void main(String[] args) {
83 | List> result = solveNQueens(4);
84 | System.out.println(result);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question45/MinNumberInArrays.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question45;
2 |
3 | import java.util.Random;
4 |
5 | /**
6 | * @Description: https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/
7 | * 剑指 Offer 45. 把数组排成最小的数
8 | * @Author tinytongtong
9 | * @Date 2020/9/11 10:59 PM
10 | * @Version
11 | */
12 | public class MinNumberInArrays {
13 |
14 | private static String minNumber(int[] nums) {
15 | if (nums == null || nums.length == 0) {
16 | return "";
17 | }
18 | String[] strs = new String[nums.length];
19 | for (int i = 0; i < nums.length; i++) {
20 | strs[i] = String.valueOf(nums[i]);
21 | }
22 | quickSort(strs, 0, strs.length - 1);
23 | StringBuilder sb = new StringBuilder();
24 | for (String item : strs) {
25 | sb.append(item);
26 | }
27 | return sb.toString();
28 | }
29 |
30 | private static void quickSort(String[] data, int start, int end) {
31 | if (data == null || start == end) {
32 | return;
33 | }
34 | int index = partition(data, start, end);
35 | if (index > start) {
36 | quickSort(data, start, index - 1);
37 | }
38 | if (index < end) {
39 | quickSort(data, index + 1, end);
40 | }
41 | }
42 |
43 | /**
44 | * 快速排序
45 | * 最坏时间复杂度O(n²)
46 | * 平均时间复杂度O(nlogn)
47 | *
48 | * @param data
49 | * @param start
50 | * @param end
51 | */
52 | private static int partition(String[] data, int start, int end) {
53 | if (data == null || data.length == 0 || start < 0 || end >= data.length || end < start) {
54 | return -1;
55 | }
56 | // 随机获取角标
57 | int randomIndex = new Random().nextInt(end - start) + start;
58 | // swap,将随机选择的数字放到end角标上
59 | String temp = data[randomIndex];
60 | data[randomIndex] = data[end];
61 | data[end] = temp;
62 |
63 | // small 表示交换到前面的元素,最后一个元素的角标
64 | int small = start - 1;
65 | for (int i = start; i < end; i++) {
66 | if ((data[i] + data[end]).compareTo(data[end] + data[i]) < 0) {
67 | small++;
68 | if (small != i) {
69 | // swap,将small和i位置的元素进行互换
70 | temp = data[small];
71 | data[small] = data[i];
72 | data[i] = temp;
73 | }
74 | }
75 | }
76 | small++;
77 | // 还原位置
78 | temp = data[small];
79 | data[small] = data[end];
80 | data[end] = temp;
81 | return small;
82 | }
83 |
84 | public static void main(String[] args) {
85 | // int[] nums = new int[]{10, 2};
86 | int[] nums = new int[]{3, 30, 34, 5, 9};
87 | String result = minNumber(nums);
88 | System.out.println(result);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question18/DeleteNodeO1.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question18;
2 |
3 | import java.util.Objects;
4 |
5 | /**
6 | * @Description: https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof/
7 | * 剑指 Offer 18. 在O(1)时间删除链表结点
8 | * @Author tinytongtong
9 | * @Date 2020/9/7 11:26 AM
10 | * @Version
11 | */
12 | public class DeleteNodeO1 {
13 | /**
14 | * Definition for singly-linked list.
15 | */
16 | private static class ListNode {
17 | int val;
18 | ListNode next;
19 |
20 | public ListNode(int val) {
21 | this.val = val;
22 | }
23 |
24 | @Override
25 | public String toString() {
26 | return "ListNode{" +
27 | "val=" + val +
28 | ", next=" + next +
29 | '}';
30 | }
31 |
32 | @Override
33 | public boolean equals(Object o) {
34 | if (this == o) return true;
35 | if (!(o instanceof ListNode)) return false;
36 | ListNode listNode = (ListNode) o;
37 | return val == listNode.val;
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | return Objects.hash(val);
43 | }
44 | }
45 |
46 | /**
47 | * 分三种情况:
48 | * ①如果pToBeDelete不是尾节点,就删除它。将它下一个节点的值赋值给pToBeDelete,同时pToBeDelete.next执行pToBeDelete.next.next
49 | * ②如果pToBeDelete是尾节点,则只能从头遍历,找到上一个pToBeDelete的上一个节点
50 | * ③如果pToBeDelete就是pHead,则将pHead置为null即可
51 | *
52 | * @param pHead
53 | * @param pToBeDelete
54 | */
55 | private static ListNode deleteNode(ListNode pHead, ListNode pToBeDelete) {
56 | if (pHead == null || pToBeDelete == null) {
57 | return null;
58 | }
59 | // 情况①
60 | if (pToBeDelete.next != null) {
61 | ListNode pNext = pToBeDelete.next;
62 | pToBeDelete.val = pNext.val;
63 | pToBeDelete.next = pNext.next;
64 | pNext = null;
65 | } else if (pHead == pToBeDelete) { // 情况③
66 | pHead = null;
67 | pToBeDelete = null;
68 | } else {// 情况②
69 | ListNode pNode = pHead;
70 | while (pNode.next != pToBeDelete) {
71 | pNode = pNode.next;
72 | }
73 | pNode.next = null;
74 | pToBeDelete = null;
75 | }
76 | return pHead;
77 | }
78 |
79 | public static void main(String[] args) {
80 | ListNode pHead = new ListNode(1);
81 | ListNode pNode2 = new ListNode(2);
82 | ListNode pNode3 = new ListNode(3);
83 | ListNode pNode4 = new ListNode(4);
84 | ListNode pNode5 = new ListNode(5);
85 | pHead.next = pNode2;
86 | pNode2.next = pNode3;
87 | pNode3.next = pNode4;
88 | pNode4.next = pNode5;
89 | System.out.println(pHead);
90 |
91 | System.out.println(deleteNode(pHead, pNode5));
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question32/PrintTreeFromTopToBottomLevelFirstNode.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question32;
2 |
3 | import java.util.LinkedList;
4 | import java.util.Queue;
5 |
6 | /**
7 | * @Description: 头条面试题
8 | * 从上到下打印二叉树,每层的第一个节点
9 | * 分层打印
10 | * @Author tinytongtong
11 | * @Date 2020/11/25 10:11 AM
12 | * @Version
13 | */
14 |
15 | public class PrintTreeFromTopToBottomLevelFirstNode {
16 | private static class TreeNode {
17 | int val;
18 | TreeNode left;
19 | TreeNode right;
20 |
21 | public TreeNode(int val) {
22 | this.val = val;
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | return "TreeNode{" +
28 | "val=" + val +
29 | ", left=" + left +
30 | ", right=" + right +
31 | '}';
32 | }
33 | }
34 |
35 | /**
36 | * 打印每层第一个节点
37 | *
38 | * @param root
39 | * @return
40 | */
41 | private static void printLevelFirstNode(TreeNode root) {
42 | if (root == null) {
43 | return;
44 | }
45 | // 1、分层打印
46 | // 2、打印每层第一个节点
47 | Queue queue = new LinkedList<>();
48 | queue.add(root);
49 | // 下一层的节点数
50 | int nextLevel = 0;
51 | // 当前层中还没有打印的节点数
52 | int toBePrinted = 1;// 从root节点开始。
53 | // 打印左侧第一个节点
54 | System.out.println(queue.peek().val);
55 | while (!queue.isEmpty()) {
56 | TreeNode node = queue.poll();
57 | if (node.left != null) {
58 | queue.add(node.left);
59 | nextLevel++;
60 | }
61 | if (node.right != null) {
62 | queue.add(node.right);
63 | nextLevel++;
64 | }
65 | toBePrinted--;
66 | if (toBePrinted == 0) {
67 | // 如果下一层没有结点,就不添加list了
68 | if (nextLevel > 0) {
69 | // 打印左侧第一个节点
70 | System.out.println(queue.peek().val);
71 | }
72 | toBePrinted = nextLevel;
73 | nextLevel = 0;
74 | }
75 | }
76 | }
77 |
78 | public static void main(String[] args) {
79 | TreeNode pRoot1 = new TreeNode(1);
80 | TreeNode pNode11 = new TreeNode(2);
81 | TreeNode pRoot12 = new TreeNode(3);
82 | pRoot1.left = pNode11;
83 | pRoot1.right = pRoot12;
84 |
85 | TreeNode pNode21 = new TreeNode(4);
86 | TreeNode pRoot22 = new TreeNode(5);
87 | pNode11.left = pNode21;
88 | pNode11.right = pRoot22;
89 |
90 | TreeNode pNode23 = new TreeNode(6);
91 | TreeNode pRoot24 = new TreeNode(7);
92 | pRoot12.left = pNode23;
93 | pRoot12.right = pRoot24;
94 | System.out.println(pRoot1);
95 | System.out.println("————————————————————————————");
96 | printLevelFirstNode(pRoot1);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question36/TreeToDoublyList.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question36;
2 |
3 | /**
4 | * @Description: https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/
5 | * 剑指 Offer 36. 二叉搜索树与双向链表
6 | * @Author tinytongtong
7 | * @Date 2020/9/9 9:43 PM
8 | * @Version
9 | */
10 | public class TreeToDoublyList {
11 | private static class Node {
12 | int val;
13 | Node left;
14 | Node right;
15 |
16 | public Node(int val) {
17 | this.val = val;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "Node{" +
23 | "val=" + val +
24 | ", left=" + left +
25 | ", right=" + right +
26 | '}';
27 | }
28 | }
29 |
30 | private static Node treeToDoublyList(Node root) {
31 | if (root == null) {
32 | return null;
33 | }
34 | // 最后一个节点
35 | Node[] pLast = new Node[1];
36 | midOrder(root, pLast);
37 | // 获取首节点
38 | while (pLast[0] != null && pLast[0].left != null) {
39 | pLast[0] = pLast[0].left;
40 | }
41 | return pLast[0];
42 | }
43 |
44 | private static void midOrder(Node root, Node[] pLast) {
45 | if (root == null) {
46 | return;
47 | }
48 | Node pCurrent = root;
49 | // 遍历左子节点
50 | if (pCurrent.left != null) {
51 | midOrder(pCurrent.left, pLast);
52 | }
53 | // 链接左子节点和中间节点
54 | pCurrent.left = pLast[0];
55 | if (pLast[0] != null) {
56 | pLast[0].right = pCurrent;
57 | }
58 | // 中间节点
59 | System.out.println(pCurrent.val);
60 | // 链接中间节点
61 | pLast[0] = pCurrent;
62 | // 遍历右子节点
63 | if (pCurrent.right != null) {
64 | midOrder(pCurrent.right, pLast);
65 | }
66 | }
67 |
68 | public static void main(String[] args) {
69 | Node root = new Node(10);
70 | Node node11 = new Node(6);
71 | Node node12 = new Node(14);
72 | root.left = node11;
73 | root.right = node12;
74 | Node node21 = new Node(4);
75 | Node node22 = new Node(8);
76 | node11.left = node21;
77 | node11.right = node22;
78 | Node node23 = new Node(12);
79 | Node node24 = new Node(16);
80 | node12.left = node23;
81 | node12.right = node24;
82 |
83 | System.out.println(root);
84 | Node result = treeToDoublyList(root);
85 | System.out.println("从小到大:");
86 | Node pLast = null;
87 | while (result != null) {
88 | System.out.println(result.val);
89 | pLast = result;
90 | result = result.right;
91 | }
92 | System.out.println("从大到小:");
93 | while (pLast != null) {
94 | System.out.println(pLast.val);
95 | pLast = pLast.left;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question07/RebuildBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question07;
2 |
3 | import java.util.HashMap;
4 |
5 | /**
6 | * @Description: https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/
7 | * 剑指 Offer 07. 重建二叉树
8 | * @Author tinytongtong
9 | * @Date 2020/9/4 10:31 AM
10 | * @Version
11 | */
12 | public class RebuildBinaryTree {
13 | private static class TreeNode {
14 | int val;
15 | TreeNode left;
16 | TreeNode right;
17 |
18 | public TreeNode(int val) {
19 | this.val = val;
20 | }
21 |
22 | @Override
23 | public String toString() {
24 | return "TreeNode{" +
25 | "val=" + val +
26 | ", left=" + left +
27 | ", right=" + right +
28 | '}';
29 | }
30 | }
31 |
32 | /**
33 | * 迭代实现
34 | * 时间复杂度O(nlogn)
35 | * 空间复杂度O(n)
36 | *
37 | * @param preorder
38 | * @param inorder
39 | * @return
40 | */
41 | private static TreeNode rebuildTree(int[] preorder, int[] inorder) {
42 | if (preorder == null || inorder == null) {
43 | return null;
44 | }
45 | // 利用HashMap定位
46 | HashMap map = new HashMap<>();
47 | for (int i = 0; i < inorder.length; i++) {
48 | map.put(inorder[i], i);
49 | }
50 |
51 | TreeNode root = buildNode(map, preorder, inorder, 0, preorder.length - 1, 0, preorder.length - 1);
52 | return root;
53 | }
54 |
55 | /**
56 | * 构建根节点,构建左子树,构建右子树
57 | *
58 | * @param preorder
59 | * @param inorder
60 | * @param startPre
61 | * @param endPre
62 | * @param startIn
63 | * @param endIn
64 | * @return
65 | */
66 | private static TreeNode buildNode(HashMap map, int[] preorder, int[] inorder, int startPre, int endPre, int startIn, int endIn) {
67 | if (startPre > endPre || startPre < 0 || endPre >= preorder.length || startIn < 0 || endIn >= preorder.length) {
68 | return null;
69 | }
70 | // 只有一个结点
71 | if (startPre == endPre) {
72 | return new TreeNode(preorder[startPre]);
73 | }
74 | TreeNode root = new TreeNode(preorder[startPre]);
75 | // 或取根节点在中序遍历数组中的角标
76 | int rootIndex = map.get(preorder[startPre]);
77 | int leftCount = rootIndex - startIn;
78 | // 左节点
79 | root.left = buildNode(map, preorder, inorder, startPre + 1, startPre + leftCount, startIn, rootIndex - 1);
80 | // 有节点
81 | root.right = buildNode(map, preorder, inorder, startPre + leftCount + 1, endPre, rootIndex + 1, endIn);
82 | return root;
83 | }
84 |
85 | public static void main(String[] args) {
86 | int[] preorder = new int[]{3, 9, 20, 15, 7};
87 | int[] inorder = new int[]{9, 3, 15, 20, 7};
88 | TreeNode result = rebuildTree(preorder, inorder);
89 | System.out.println(result);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question27/MirrorBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question27;
2 |
3 |
4 | import java.util.Stack;
5 |
6 | /**
7 | * @Description: https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/
8 | * 剑指 Offer 27. 二叉树的镜像
9 | * @Author tinytongtong
10 | * @Date 2020/9/8 5:07 PM
11 | * @Version
12 | */
13 | public class MirrorBinaryTree {
14 | private static class TreeNode {
15 | int val;
16 | TreeNode left;
17 | TreeNode right;
18 |
19 | public TreeNode(int val) {
20 | this.val = val;
21 | }
22 |
23 | @Override
24 | public String toString() {
25 | return "TreeNode{" +
26 | "val=" + val +
27 | ", left=" + left +
28 | ", right=" + right +
29 | '}';
30 | }
31 | }
32 |
33 | /**
34 | * 递归解法
35 | *
36 | * @param root
37 | * @return
38 | */
39 | private static TreeNode mirrorTreeByRecursive(TreeNode root) {
40 | if (root == null) {
41 | return null;
42 | }
43 | TreeNode temp = root.left;
44 | root.left = root.right;
45 | root.right = temp;
46 | mirrorTreeByRecursive(root.left);
47 | mirrorTreeByRecursive(root.right);
48 | return root;
49 | }
50 |
51 | /**
52 | * 迭代解法
53 | *
54 | * @param root
55 | * @return
56 | */
57 | private static TreeNode mirrorTreeByIteration(TreeNode root) {
58 | if (root == null) {
59 | return null;
60 | }
61 | Stack stack = new Stack<>();
62 | stack.push(root);
63 | while (!stack.isEmpty()) {
64 | TreeNode node = stack.pop();
65 | // swap
66 | TreeNode temp = node.left;
67 | node.left = node.right;
68 | node.right = temp;
69 | if (node.left != null) {
70 | stack.push(node.left);
71 | }
72 | if (node.right != null) {
73 | stack.push(node.right);
74 | }
75 | }
76 | return root;
77 | }
78 |
79 | public static void main(String[] args) {
80 | TreeNode pRoot1 = new TreeNode(8);
81 | TreeNode pNode11 = new TreeNode(6);
82 | TreeNode pRoot12 = new TreeNode(10);
83 | pRoot1.left = pNode11;
84 | pRoot1.right = pRoot12;
85 |
86 | TreeNode pNode21 = new TreeNode(5);
87 | TreeNode pRoot22 = new TreeNode(7);
88 | pNode11.left = pNode21;
89 | pNode11.right = pRoot22;
90 |
91 | TreeNode pNode23 = new TreeNode(9);
92 | TreeNode pRoot24 = new TreeNode(11);
93 | pRoot12.left = pNode23;
94 | pRoot12.right = pRoot24;
95 |
96 | System.out.println(pRoot1);
97 | // 递归
98 | // System.out.println(mirrorTreeByRecursive(pRoot1));
99 | // 迭代
100 | System.out.println(mirrorTreeByIteration(pRoot1));
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/question/question_0105/BuildTreeFromPreOrderAndInOrder.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.question.question_0105;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * @Description: 105. 从前序与中序遍历序列构造二叉树
7 | * https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
8 | * @Author wangjianzhou
9 | * @Date 2022/2/23 5:23 PM
10 | */
11 | public class BuildTreeFromPreOrderAndInOrder {
12 |
13 | public static void main(String[] args) {
14 | int[] preorder = new int[]{1, 2, 3};
15 | int[] inorder = new int[]{2, 3, 1};
16 | BuildTreeFromPreOrderAndInOrder buildTree = new BuildTreeFromPreOrderAndInOrder();
17 | TreeNode tree = buildTree.buildTree(preorder, inorder);
18 | buildTree.logTree(tree);
19 | }
20 |
21 | private TreeNode buildTree(int[] preorder, int[] inorder) {
22 | return buildNode(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
23 | }
24 |
25 | private TreeNode buildNode(int[] preorder, int[] inorder, int preStart, int preEnd, int inStart, int inEnd) {
26 | if (preStart > preEnd || inStart > inEnd || preStart < 0 || preEnd >= preorder.length
27 | || inStart < 0 || inEnd >= inorder.length) return null;
28 | // 查找root的值。前序遍历的第一个数据就是
29 | int midNodeValue = preorder[preStart];
30 | // 在中序遍历的数组中,找到root值的位置。借此区分出左子树的数据,进而区分右子树的数据。
31 | int midNodeIndex = inStart;
32 | for (int i = inStart; i <= inEnd; i++) {
33 | if (midNodeValue == inorder[i]) {
34 | midNodeIndex = i;
35 | break;
36 | }
37 | }
38 | int leftCount = midNodeIndex - inStart;
39 | TreeNode left = buildNode(preorder, inorder, preStart + 1, preStart + leftCount, inStart, inStart + leftCount - 1);
40 | TreeNode right = buildNode(preorder, inorder, preStart + leftCount + 1, preEnd, inStart + leftCount + 1, inEnd);
41 | TreeNode node = new TreeNode(midNodeValue, left, right);
42 | return node;
43 | }
44 |
45 | private void logTree(TreeNode tree) {
46 | ArrayList result = new ArrayList<>();
47 | if (tree == null) {
48 | System.out.println(result);
49 | return;
50 | }
51 | logTreeCore(tree, result);
52 | System.out.println(result);
53 | }
54 |
55 | private void logTreeCore(TreeNode tree, ArrayList result) {
56 | if (tree == null) {
57 | result.add(null);
58 | return;
59 | }
60 | result.add(tree.val);
61 | logTreeCore(tree.left, result);
62 | logTreeCore(tree.right, result);
63 | }
64 |
65 | private static final class TreeNode {
66 | int val;
67 | TreeNode left;
68 | TreeNode right;
69 |
70 | TreeNode() {
71 | }
72 |
73 | TreeNode(int val) {
74 | this.val = val;
75 | }
76 |
77 | TreeNode(int val, TreeNode left, TreeNode right) {
78 | this.val = val;
79 | this.left = left;
80 | this.right = right;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tinytongtong/leetcodetest/targetoffer/question23/MeetingNodeInCycle1.java:
--------------------------------------------------------------------------------
1 | package com.tinytongtong.leetcodetest.targetoffer.question23;
2 |
3 |
4 | /**
5 | * @Description: 美团面试题:找到链表中环的入口节点,如果无环就返回空
6 | * @Author tinytongtong
7 | * @Date 2020/9/8 9:20 AM
8 | * @Version
9 | */
10 | public class MeetingNodeInCycle1 {
11 | private static class ListNode {
12 | int val;
13 | ListNode next;
14 |
15 | public ListNode(int val) {
16 | this.val = val;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return "ListNode{" +
22 | "val=" + val +
23 | '}';
24 | }
25 | }
26 |
27 | private static ListNode entryNodeOfLoop(ListNode head) {
28 | // 1、先根据快慢指针确定是否有环。如果有环就找到一个环内节点,如果没有就返回null
29 | ListNode cycleNode = findCycleNode(head);
30 | // 无环
31 | if (cycleNode == null) {
32 | return null;
33 | }
34 | // 2、然后确定环的个数n。快慢指针,相遇的时候,慢指针走过的距离
35 | int n = countCycleNodeNum(cycleNode);
36 | // 3、然后两个指针P1和P2,均指向链表头部节点,P1先移动n,然后P1和P2以相同的速度前进,它两相遇的节点就是入口节点。
37 | ListNode p1 = head, p2 = head;
38 | while (n > 0) {
39 | p1 = p1.next;
40 | n--;
41 | }
42 | while (p1.val != p2.val) {
43 | p1 = p1.next;
44 | p2 = p2.next;
45 | }
46 | return p1;
47 | }
48 |
49 | /**
50 | * 判断链表是否有环,如果有,就返回环中的一个node;
51 | * 如果没有就返回null;
52 | *
53 | * @param head
54 | * @return
55 | */
56 | private static ListNode findCycleNode(ListNode head) {
57 | if (head == null) {
58 | return null;
59 | }
60 | ListNode slow = head, fast = head;
61 | while (slow != null && fast != null) {
62 | slow = slow.next;
63 | if (fast.next != null) {
64 | fast = fast.next.next;
65 | } else { // 无环
66 | return null;
67 | }
68 | if (slow != null && fast != null && slow.val == fast.val) {
69 | return fast;
70 | }
71 | }
72 | return null;
73 | }
74 |
75 | /**
76 | * 统计环形链表中环的个数
77 | *
78 | * @param node
79 | * @return
80 | */
81 | private static int countCycleNodeNum(ListNode node) {
82 | if (node == null) {
83 | return 0;
84 | }
85 | int n = 1;
86 | ListNode slow = node.next;
87 | ListNode fast = node.next.next;
88 | while (slow.val != fast.val) {
89 | slow = slow.next;
90 | fast = fast.next.next;
91 | n++;
92 | }
93 | return n;
94 | }
95 |
96 | public static void main(String[] args) {
97 | ListNode pHead = new ListNode(1);
98 | ListNode pNode2 = new ListNode(2);
99 | ListNode pNode3 = new ListNode(3);
100 | ListNode pNode4 = new ListNode(4);
101 | ListNode pNode5 = new ListNode(5);
102 | pHead.next = pNode2;
103 | pNode2.next = pNode3;
104 | pNode3.next = pNode4;
105 | pNode4.next = pNode5;
106 | pNode5.next = pNode5;
107 | System.out.println(pHead);
108 |
109 | System.out.println(entryNodeOfLoop(pHead));
110 | }
111 | }
112 |
--------------------------------------------------------------------------------