21 | * 先对 g 和 s 排序升序,然后从小到大遍历s, 满足 s[j]>=g[i]的就计数 22 | *
23 | * 时间复杂度:O(m log m + n log n)
24 | * 空间复杂度:取决于排序算法
25 | */
26 | public class AssignCookies0 extends AssignCookies {
27 | @Override
28 | public int findContentChildren(int[] g, int[] s) {
29 | Arrays.sort(g);
30 | Arrays.sort(s);
31 | int i = 0;
32 | int count = 0;
33 | for (int j = 0; j < s.length; j++) {
34 | if (i >= g.length) {
35 | break;
36 | }
37 | if (s[j] >= g[i]) {
38 | count++;
39 | i++;
40 | }
41 | }
42 | return count;
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/AverageOfLevelsInBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | import java.util.ArrayList;
6 | import java.util.LinkedList;
7 | import java.util.List;
8 | import java.util.Queue;
9 |
10 | /**
11 | * LeetCode 637. Average of Levels in Binary Tree
12 | * Question https://leetcode.com/problems/average-of-levels-in-binary-tree/
13 | * 关键题设:无
14 | *
15 | * @auther brian
16 | * @since 2022/9/2 22:26
17 | */
18 | public class AverageOfLevelsInBinaryTree {
19 | public List
22 | * 用树的高度来解决,后序遍历
23 | */
24 | public class BalancedBinaryTree0 extends BalancedBinaryTree {
25 | @Override
26 | public boolean isBalanced(TreeNode root) {
27 | if (root == null) {
28 | return true;
29 | }
30 | return getHeight(root) != -1;
31 | }
32 |
33 | /**
34 | * 如果cur是平衡的,则返回高度,否则返回-1
35 | */
36 | public int getHeight(TreeNode cur) {
37 | if (cur == null) {
38 | return 0;
39 | }
40 | int leftHeight = getHeight(cur.left);
41 | if (leftHeight == -1) {
42 | return -1;
43 | }
44 | int rightHeight = getHeight(cur.right);
45 | if (rightHeight == -1) {
46 | return -1;
47 | }
48 |
49 | if (Math.abs(leftHeight - rightHeight) > 1) {
50 | return -1;
51 | } else {
52 | return Math.max(leftHeight, rightHeight) + 1;
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/BinarySearch.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * LeetCode 704. Binary Search
5 | * Question: https://leetcode.com/problems/binary-search/
6 | * 关键题设:无
7 | *
8 | * @auther brian
9 | * @since 2022/8/8 21:00
10 | */
11 | public class BinarySearch {
12 |
13 | public int search(int[] nums, int target) {
14 | int low = 0;
15 | int high = nums.length - 1;
16 | int mid = low + (high - low) / 2;
17 |
18 | while (low <= high) {
19 | if (target == nums[mid]) {
20 | return mid;
21 | } else if (target > nums[mid]) {
22 | low = mid + 1;
23 | } else {
24 | high = mid - 1;
25 | }
26 | // 这句也可以在循环开始处计算
27 | mid = low + (high - low) / 2;
28 | }
29 | return -1;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/FindModeInBinarySearchTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * LeetCode 501. Find Mode in Binary Search Tree
10 | * Question: https://leetcode.com/problems/find-mode-in-binary-search-tree/
11 | * 关键题设:无
12 | *
13 | * @auther brian
14 | * @since 2022/9/7 23:07
15 | */
16 | public class FindModeInBinarySearchTree {
17 | public int[] findMode(TreeNode root) {
18 | return null;
19 | }
20 |
21 | /**
22 | * 递归
23 | *
24 | * 中序遍历,一次遍历即可:边统计频次,边更新int[]
25 | */
26 | public class FindModeInBinarySearchTree0 extends FindModeInBinarySearchTree {
27 | List
23 | * 时间复杂度 O(n)
24 | * 空间复杂度 O(1)
25 | * 分析可见 https://leetcode.com/articles/linked-list-cycle/
26 | */
27 | public class LinkedListCycle0 extends LinkedListCycle {
28 | @Override
29 | public boolean hasCycle(ListNode head) {
30 | if (head == null) {
31 | return false;
32 | }
33 |
34 | ListNode fast = head;
35 | ListNode slow = head;
36 | while (fast.next != null && fast.next.next != null) {
37 | fast = fast.next.next;
38 | slow = slow.next;
39 | if (fast == slow) {
40 | return true;
41 | }
42 | }
43 | return false;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MaximumDepthOfBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 104. Maximum Depth of Binary Tree
7 | * Question: https://leetcode.com/problems/maximum-depth-of-binary-tree/
8 | * 关键题设: maximum depth
9 | *
10 | * @auther brian
11 | * @since 2022/9/3 15:33
12 | */
13 | public class MaximumDepthOfBinaryTree {
14 | public int maxDepth(TreeNode root) {
15 | return 0;
16 | }
17 |
18 | /**
19 | * 递归解法
20 | *
21 | * 根节点的高度就是二叉树的最大深度
22 | * 后序遍历: 左子树高度,右子树高度,cur的高度
23 | */
24 | public class MaximumDepthOfBinaryTree0 extends MaximumDepthOfBinaryTree {
25 | @Override
26 | public int maxDepth(TreeNode root) {
27 | if (root == null) {
28 | return 0;
29 | }
30 |
31 | int maxLeftDepth = maxDepth(root.left);
32 | int maxRightDepth = maxDepth(root.right);
33 | return Math.max(maxLeftDepth, maxRightDepth) + 1;
34 | }
35 | }
36 |
37 | // TODO 迭代法: 层序遍历即可
38 | }
39 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MergeTwoBinaryTrees.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 617. Merge Two Binary Trees
7 | * Question: https://leetcode.com/problems/merge-two-binary-trees/
8 | * 关键题设:无
9 | *
10 | * @auther brian
11 | * @since 2022/9/7 21:43
12 | */
13 | public class MergeTwoBinaryTrees {
14 |
15 | public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
16 | return null;
17 | }
18 |
19 | /**
20 | * 递归
21 | *
22 | * 先序遍历/后序遍历都行
23 | */
24 | public class MergeTwoBinaryTrees0 extends MergeTwoBinaryTrees {
25 | @Override
26 | public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
27 | // 终止条件
28 | if (root1 == null && root2 == null) {
29 | return null;
30 | } else if (root1 == null) {
31 | return root2;
32 | } else if (root2 == null) {
33 | return root1;
34 | }
35 |
36 | // merge current
37 | TreeNode cur = new TreeNode(root1.val + root2.val);
38 | // merge left
39 | TreeNode left = mergeTrees(root1.left, root2.left);
40 | // merge right
41 | TreeNode right = mergeTrees(root1.right, root2.right);
42 |
43 | cur.left = left;
44 | cur.right = right;
45 |
46 | return cur;
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MergeTwoSortedLists.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.ListNode;
4 |
5 | /**
6 | * Created by Brian on 2016/5/4.
7 | * LeetCode 21. Merge Two Sorted Lists
8 | * Question:https://leetcode.com/problems/merge-two-sorted-lists/
9 | * 关键题设: two sorted linked lists
10 | */
11 | public class MergeTwoSortedLists {
12 |
13 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
14 | return null;
15 | }
16 |
17 | /**
18 | * 链表的基本操作
19 | * 主要是要先添加一个头部,方便代码一致
20 | * 用一个指针指示当前节点的上一个节点,每次添加较小的那个
21 | * 直至一个其中一个遍历完,直接把另一链表全部接上即可
22 | *
23 | * 设l1长度为n1,l2长度n2
24 | * 时间复杂度:最坏情况O(n1+n2)
25 | * 空间复杂度 O(1)
26 | */
27 | public class MergeTwoSortedLists0 extends MergeTwoSortedLists {
28 | @Override
29 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
30 | ListNode head = new ListNode(0);
31 | ListNode now = head;
32 | while (l1 != null && l2 != null) {
33 | if (l1.val < l2.val) {
34 | //now.next = new ListNode(l1.val);
35 | now.next = l1;
36 | l1 = l1.next;
37 | } else {
38 | //now.next = new ListNode(l2.val);
39 | now.next = l2;
40 | l2 = l2.next;
41 | }
42 | now = now.next;
43 | }
44 | if (l1 != null) {
45 | now.next = l1;
46 | }
47 | if (l2 != null) {
48 | now.next = l2;
49 | }
50 | return head.next;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MinimumAbsoluteDifferenceInBST.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 530. Minimum Absolute Difference in BST
7 | * Question https://leetcode.com/problems/minimum-absolute-difference-in-bst/
8 | * 关键题设:无
9 | *
10 | * @auther brian
11 | * @since 2022/9/7 22:47
12 | */
13 | public class MinimumAbsoluteDifferenceInBST {
14 | public int getMinimumDifference(TreeNode root) {
15 | return 0;
16 | }
17 |
18 | /**
19 | * 递归
20 | */
21 | public class MinimumAbsoluteDifferenceInBST0 extends MinimumAbsoluteDifferenceInBST {
22 | private TreeNode pre;
23 | private int result = Integer.MAX_VALUE;
24 |
25 | @Override
26 | public int getMinimumDifference(TreeNode root) {
27 | if (root == null) {
28 | return 0;
29 | }
30 | traversal(root);
31 | return result;
32 | }
33 |
34 | /**
35 | * 中序遍历
36 | */
37 | public void traversal(TreeNode root) {
38 | if (root == null) {
39 | return;
40 | }
41 |
42 | traversal(root.left);
43 | if (pre != null) {
44 | result = Math.min(root.val - pre.val, result);
45 | }
46 | pre = root;
47 |
48 | traversal(root.right);
49 |
50 | }
51 |
52 | }
53 |
54 | // TODO 迭代
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MinimumDepthOfBinaryTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 111. Minimum Depth of Binary Tree
7 | * Question: https://leetcode.com/problems/minimum-depth-of-binary-tree/
8 | * 关键题设:The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
9 | *
10 | * @auther brian
11 | * @since 2022/9/3 15:47
12 | */
13 | public class MinimumDepthOfBinaryTree {
14 | public int minDepth(TreeNode root) {
15 | return 0;
16 | }
17 |
18 | /**
19 | * 递归
20 | *
21 | * 后序遍历
22 | *
23 | * 注意:子树为空的情况
24 | */
25 | public class MinimumDepthOfBinaryTree0 extends MinimumDepthOfBinaryTree {
26 | @Override
27 | public int minDepth(TreeNode root) {
28 | if (root == null) {
29 | return 0;
30 | }
31 | int leftMinDepth = minDepth(root.left);
32 | int rightMinDepth = minDepth(root.right);
33 |
34 | if (root.left != null && root.right == null) {
35 | return leftMinDepth + 1;
36 | } else if (root.left == null && root.right != null) {
37 | return rightMinDepth + 1;
38 | } else {
39 | return Math.min(leftMinDepth, rightMinDepth) + 1;
40 | }
41 | }
42 | }
43 |
44 | // TODO 层序遍历,左右孩子都空说明到最低点了
45 | }
46 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/PathSum.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 112. Path Sum
7 | * Question: https://leetcode.com/problems/path-sum/
8 | * 关键题设:无
9 | *
10 | * @auther brian
11 | * @since 2022/9/6 21:41
12 | */
13 | public class PathSum {
14 | public boolean hasPathSum(TreeNode root, int targetSum) {
15 | return false;
16 | }
17 |
18 | public class PathSum0 extends PathSum {
19 | @Override
20 | public boolean hasPathSum(TreeNode root, int targetSum) {
21 | // 终止条件: null or 叶子节点
22 | if (root == null) {
23 | return false;
24 | }
25 | if (root.left == null && root.right == null) {
26 | return targetSum - root.val == 0;
27 | }
28 |
29 | // 本层逻辑
30 | return hasPathSum(root.left, targetSum - root.val)
31 | || hasPathSum(root.right, targetSum - root.val);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/PowerOfTwo.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * Created by brian on 16/5/23.
5 | * LeetCode 231. Power of Two
6 | * Question:https://leetcode.com/problems/power-of-two/
7 | * 关键题设:power of two
8 | */
9 | public class PowerOfTwo {
10 | public boolean isPowerOfTwo(int n) {
11 | return false;
12 | }
13 |
14 | /**
15 | * 2的幂实际上就是通过1向右移位得到的,每乘以2就是向右移动一位
16 | * 所以其二进制高位只有一个1,其余位为0
17 | * 此方法好像并不受小于0的数影响
18 | */
19 | public class PowerOfTwo0 extends PowerOfTwo {
20 | @Override
21 | public boolean isPowerOfTwo(int n) {
22 | // if(n<0) return false;//多余,while能直接办到
23 | boolean hasOne = false;
24 | while (n > 0) {
25 | if ((n & 1) == 1) {
26 | if (hasOne) {//已经有1了,再次遇到1,非2的幂
27 | return false;
28 | } else {//第一次1
29 | hasOne = true;
30 | }
31 | }
32 | n >>= 1;//右移一位
33 | }
34 | return hasOne;
35 | }
36 | }
37 |
38 | /**
39 | * n 与 n-1 按位与
40 | * 好像并不受小于0的数影响,小于稳定返回false
41 | * 注意零值
42 | */
43 | public class PowerOfTwo1 extends PowerOfTwo {
44 | @Override
45 | public boolean isPowerOfTwo(int n) {
46 | return n > 0 && (n & (n - 1)) == 0;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/RemoveDuplicatesfromSortedArray.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * Created by Brian on 2016/4/26.
5 | * LeetCode 26. Remove Duplicates from Sorted Array
6 | * Question:https://leetcode.com/problems/remove-duplicates-from-sorted-array/
7 | * 关键题设: a sorted array,remove the duplicates in place
8 | */
9 | public class RemoveDuplicatesfromSortedArray {
10 | public int removeDuplicates(int[] nums) {
11 | return 0;
12 | }
13 |
14 | /**
15 | * 双指针,一个指示distinct的结尾,记为i,一个用于扫描,记为j
16 | * 当扫描指针所指示nums[j]和nums[j+i]值不同时,则赋值nums[i],并increment i指针。
17 | * 时间复杂度 O(n)
18 | * 空间复杂度 O(1)
19 | */
20 | public class RemoveDuplicatesfromSortedArray0 extends RemoveDuplicatesfromSortedArray {
21 | @Override
22 | public int removeDuplicates(int[] nums) {
23 | if (nums.length <= 1) return nums.length;
24 | int i = 0;
25 | for (int j = 0; j < nums.length - 1; j++) {
26 | if (nums[j] < nums[j + 1]) {
27 | nums[++i] = nums[j + 1];
28 | }
29 | }
30 | return i + 1;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ReverseString.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * Created by brian on 16/5/30.
5 | * LeetCode 344. Reverse String
6 | * Question:https://leetcode.com/problems/reverse-string/
7 | * 关键题设:none
8 | */
9 | public class ReverseString {
10 | public void reverseString(char[] s) {
11 |
12 | }
13 |
14 | /**
15 | * 首尾互换就行了
16 | * 将第i个字符和第length-1-i个字符交换
17 | * 0 ≤ i ≤ length/2-1
18 | * 这里边界不要搞错了,第一次就是想着少交换中间的一个,i 取的 0≤i≤(length-1)/2
19 | * 然后测试案例"a."没通过
20 | *
21 | * 例子:
22 | * s a b c d e f
23 | * i 0 1 2 3 4 5
24 | * length = 6,中间的 i = 3,其实取到 i = 2 即可
25 | * a a b c d e
26 | * i 0 1 2 3 4
27 | * length = 5,中间的 i = 2,其实取到 i = 1 即可
28 | *
29 | * 相关链接:http://javahungry.blogspot.com/2014/12/5-ways-to-reverse-string-in-java-with-example.html
30 | *
31 | * 时间复杂度 O(n/2)
32 | * 空间复杂度 O(1)
33 | */
34 | public class ReverseString0 extends ReverseString {
35 | @Override
36 | public void reverseString(char[] s) {
37 | int length = s.length;
38 | char tmp;
39 | for (int i = 0; i < length / 2; i++) {
40 | tmp = s[i];
41 | s[i] = s[length - 1 - i];
42 | s[length - 1 - i] = tmp;
43 | }
44 | }
45 | }
46 |
47 | public class RevereString1 extends ReverseString {
48 | public void reverseString(char[] s) {
49 | int l = 0;
50 | int r = s.length - 1;
51 | while (l < r) {
52 | s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中
53 | s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
54 | s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
55 | l++;
56 | r--;
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ReverseStringII.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * LeetCode 541. Reverse String II
5 | * Question: https://leetcode.com/problems/reverse-string-ii/
6 | * 关键题设:无
7 | *
8 | * @auther brian
9 | * @since 2022/9/9 00:05
10 | */
11 | public class ReverseStringII {
12 |
13 | public String reverseStr(String s, int k) {
14 | return null;
15 | }
16 |
17 | public class ReverseStringII0 extends ReverseStringII {
18 | @Override
19 | public String reverseStr(String s, int k) {
20 | char[] ss = s.toCharArray();
21 | int len = 2 * k;
22 | for (int i = 0; i < ss.length; i = i + len) {
23 | reversePart(ss, i, Math.min(i + k, ss.length));
24 | }
25 | return new String(ss);
26 | }
27 |
28 | public void reversePart(char[] ss, int lowInclusive, int highExclusive) {
29 | char tmp;
30 | for (int i = lowInclusive; i < lowInclusive + (highExclusive - lowInclusive) / 2; i++) {
31 | tmp = ss[i];
32 | ss[i] = ss[highExclusive + lowInclusive - 1 - i];
33 | ss[highExclusive + lowInclusive - 1 - i] = tmp;
34 | }
35 | }
36 |
37 | public void reversePart2(char[] ss, int lowInclusive, int highExclusive) {
38 | int highInclusive = highExclusive - 1;
39 | char tmp;
40 | while (lowInclusive < highInclusive) {
41 | tmp = ss[lowInclusive];
42 | ss[lowInclusive] = ss[highInclusive];
43 | ss[highInclusive] = tmp;
44 | lowInclusive++;
45 | highInclusive--;
46 | }
47 | }
48 |
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SearchInBinarySearchTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 700. Search in a Binary Search Tree
7 | * Question: https://leetcode.com/problems/search-in-a-binary-search-tree/
8 | * 关键题设:无
9 | *
10 | * @auther brian
11 | * @since 2022/9/7 21:51
12 | */
13 | public class SearchInBinarySearchTree {
14 |
15 | public TreeNode searchBST(TreeNode root, int val) {
16 | return null;
17 | }
18 |
19 | /**
20 | * 递归
21 | */
22 | public class SearchInBinarySearchTree0 extends SearchInBinarySearchTree {
23 | @Override
24 | public TreeNode searchBST(TreeNode root, int val) {
25 | // 终止条件
26 | if (root == null) {
27 | return null;
28 | }
29 |
30 | if (root.val == val) {
31 | return root;
32 | } else if (root.val > val) {
33 | return searchBST(root.left, val);
34 | } else {
35 | return searchBST(root.right, val);
36 | }
37 | }
38 | }
39 |
40 | /**
41 | * 迭代
42 | */
43 | public class SearchInBinarySearchTree01 extends SearchInBinarySearchTree {
44 | @Override
45 | public TreeNode searchBST(TreeNode root, int val) {
46 | TreeNode cur = root;
47 | while (cur != null) {
48 | if (cur.val == val) {
49 | return cur;
50 | } else if (cur.val > val) {
51 | cur = cur.left;
52 | } else {
53 | cur = cur.right;
54 | }
55 | }
56 | return null;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SearchInsertPosition.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | /**
4 | * LeetCode 35. Search Insert Position
5 | * Question https://leetcode.com/problems/search-insert-position/
6 | * 关键题设:array of distinct integers
7 | *
8 | * @auther brian
9 | * @since 2022/5/8 15:16
10 | */
11 | public class SearchInsertPosition {
12 |
13 | public int searchInsert(int[] nums, int target) {
14 | return 0;
15 | }
16 |
17 | /**
18 | * 如果target在nums中找不到,则最终一定是low>high,且low=high+1
19 | * 此时,如果 target < nums[mid], 则说明最后一次low=high=mid, 然后分支走的是 high = mid - 1,
20 | * 从而循环结束时,mid=low>high, 插入位置为 mid,即low;
21 | * 如果 target > nums[mid],则说明最后一次low=high=mid, 然后分支走的是 low = mid + 1,
22 | * 从而循环结束时,mid=high < low, 插入位置为 mid+1,也即low;
23 | */
24 | public static class SearchInsertPosition0 extends SearchInsertPosition {
25 | @Override
26 | public int searchInsert(int[] nums, int target) {
27 | int low = 0;
28 | int high = nums.length - 1;
29 | while (low <= high) {
30 | int mid = low + (high - low) / 2;
31 | if (nums[mid] == target) {
32 | return mid;
33 | } else if (nums[mid] > target) {
34 | high = mid - 1;
35 | } else {
36 | low = mid + 1;
37 | }
38 | }
39 |
40 | return low;
41 | }
42 | }
43 | }
44 |
45 | // System.out.println("target:" + target + ", mid: " + mid);
46 | // System.out.println("low:" + low + ", high: " + high);
47 | //
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SumOfLeftLeaves.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 404. Sum of Left Leaves
7 | * Question https://leetcode.com/problems/sum-of-left-leaves/
8 | * 关键题设:A leaf is a node with no children.
9 | * A left leaf is a leaf that is the left child of another node.
10 | *
11 | * @auther brian
12 | * @since 2022/9/6 00:00
13 | */
14 | public class SumOfLeftLeaves {
15 |
16 | public int sumOfLeftLeaves(TreeNode root) {
17 | return 0;
18 | }
19 |
20 | /**
21 | * 递归
22 | * 后序遍历
23 | */
24 | public class SumOfLeftLeaves0 extends SumOfLeftLeaves {
25 | @Override
26 | public int sumOfLeftLeaves(TreeNode root) {
27 | // 终止条件
28 | if (root == null) {
29 | return 0;
30 | }
31 | // 单层逻辑
32 | int leftSum = sumOfLeftLeaves(root.left);
33 | if (root.left != null && root.left.left == null && root.left.right == null) {
34 | // 仅这个if条件下才会有val值贡献进来
35 | leftSum = root.left.val;
36 | }
37 | int rightSum = sumOfLeftLeaves(root.right);
38 |
39 | return leftSum + rightSum;
40 | }
41 | }
42 |
43 | // TODO 迭代写法
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ValidParentheses.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.easy;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * LeetCode 20. Valid Parentheses
7 | * Question:https://leetcode.com/problems/valid-parentheses/description/
8 | * 关键题设:无
9 | */
10 | public class ValidParentheses {
11 | public boolean isValid(String s) {
12 | return false;
13 | }
14 |
15 | /**
16 | * 栈来存
17 | * 左括号直接入栈,右括号则看是否和栈顶元素匹配
18 | * 注意事项:栈为空时,需要判断,要避免 java.util.EmptyStackException
19 | *
20 | * 时间复杂度 O(n)
21 | * 空间复杂度 O(n)
22 | */
23 | public class ValidParentheses0 extends ValidParentheses {
24 | @Override
25 | public boolean isValid(String s) {
26 | if (s == null || s.isEmpty()) {
27 | return true;
28 | }
29 | char[] chars = s.toCharArray();
30 | Stack
20 | * 1. dp数组以及下标含义: dp[i+1][j+1] 表示 s的[0...i] 中 子序列为t[0...j]的不同子序列的个数
21 | * 2. 递推关系:
22 | * if(s[i]==t[j]) dp[i+1][j+1] = dp[i][j]+dp[i][j+1], 表示使用s[i] 和不使用s[i]的不同子序列的个数
23 | * else dp[i+1][j+1]=dp[i][j+1], 表示不使用s[i]
24 | * 3. 初始化:
25 | * dp[i][0] 都是1, 表示t为空串时,子序列个数为1,即 "" 是任意字符串的子序列,且最只有一个;
26 | * dp[0][j]=0,(j>0) 表示没有子序列;
27 | * dp[0][0]=1, 表示 "" 是 "" 的子序列
28 | * 4. 遍历顺序:从左到右
29 | *
30 | * 最后返回 dp[s.len][t.len]
31 | */
32 | public class DistinctSubsequences0 extends DistinctSubsequences {
33 | @Override
34 | public int numDistinct(String s, String t) {
35 | int[][] dp = new int[s.length() + 1][t.length() + 1];
36 | // 很关键的初始化
37 | for (int i = 0; i < s.length(); i++) {
38 | dp[i][0] = 1;
39 | }
40 | for (int j = 0; j < t.length(); j++) {
41 | dp[0][j] = 0;
42 | }
43 | dp[0][0] = 1;
44 |
45 | for (int i = 0; i < s.length(); i++) {
46 | for (int j = 0; j < t.length(); j++) {
47 | if (t.charAt(j) == s.charAt(i)) {
48 | dp[i + 1][j + 1] = dp[i][j] + dp[i][j + 1];
49 | } else {
50 | dp[i + 1][j + 1] = dp[i][j + 1];
51 | }
52 | }
53 | }
54 | return dp[s.length()][t.length()];
55 | }
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/hard/TrappingRainWater.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.hard;
2 |
3 | /**
4 | * LeetCode 42. Trapping Rain Water
5 | * Question: https://leetcode.com/problems/trapping-rain-water/
6 | * 关键题设: 无
7 | *
8 | * @auther brian
9 | * @since 2022/12/2 23:32
10 | */
11 | public class TrappingRainWater {
12 |
13 | /**
14 | * 按列求
15 | * 对于每一列,找出其左侧最高列的高度 max_left 和 右侧最高列的高度 max_right
16 | * 如果 min(max_left, max_right) > 当前列高度,则 该列对应雨水 为 min(max_left, max_right)- height[i], 否则为0
17 | * 累加每列的雨水即可
18 | *
19 | * 每一列的max_left和max_right可用动态规划求
20 | *
21 | * 时间复杂度 O(n) 三次遍历
22 | * 空间复杂度 O(n) 两个长度n的数组存每一列的max_left和max_right
23 | */
24 | class Solution {
25 | public int trap(int[] height) {
26 | int[] leftMax = new int[height.length];
27 | int[] rightMax = new int[height.length];
28 | // leftMax[i]表示0~i-1的最大值
29 | for (int i = 1; i < height.length; i++) {
30 | leftMax[i] = Math.max(leftMax[i - 1], height[i - 1]);
31 | }
32 | // rightMax[i]表示i+1~n的最大值
33 | for (int i = height.length - 2; i >= 0; i--) {
34 | rightMax[i] = Math.max(rightMax[i + 1], height[i + 1]);
35 | }
36 |
37 | int total = 0;
38 | for (int i = 0; i < height.length; i++) {
39 | int min = Math.min(leftMax[i], rightMax[i]);
40 | if (min > height[i]) {
41 | total += (min - height[i]);
42 | }
43 | }
44 | return total;
45 |
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/BinaryTreeLevelOrderTraversalII.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * LeetCode 107. Binary Tree Level Order Traversal II
9 | * Question: https://leetcode.com/problems/binary-tree-level-order-traversal-ii/
10 | * 关键题设:无
11 | *
12 | * @auther brian
13 | * @since 2022/9/2 00:04
14 | */
15 | public class BinaryTreeLevelOrderTraversalII {
16 | public List
20 | * 面积=高*宽, 即 S(i,j)= min{h[i],h[j]}*(j-i)
21 | * left,right分别指向两边,然后依次向内移动高度较小的一边,直至两指针相遇。
22 | * 因为向内移动,必然会使得宽度变窄,而高度又是取小,
23 | * 所以移动高度大的一边面积一定变小,而移动高度小的一边面积可能增大
24 | *
25 | * 时间复杂度 O(n)
26 | * 空间复杂度 O(1)
27 | */
28 | public class ContainerWithMostWater0 extends ContainerWithMostWater {
29 | @Override
30 | public int maxArea(int[] height) {
31 | int left = 0, right = height.length - 1;
32 | int area = 0;
33 | int maxArea = 0;
34 | while (left < right) {
35 | area = Math.min(height[left], height[right]) * (right - left);
36 | maxArea = Math.max(area, maxArea);
37 | if (height[left] < height[right]) {
38 | left++;
39 | } else {
40 | right--;
41 | }
42 | }
43 | return maxArea;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/CopyListWithRandomPointer.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * LeetCode 138. Copy List with Random Pointer
8 | * Question: https://leetcode.com/problems/copy-list-with-random-pointer/
9 | * 关键题设:None of the pointers in the new list should point to nodes in the original list.
10 | *
11 | * @auther brian
12 | * @since 2022/12/11 19:47
13 | */
14 | public class CopyListWithRandomPointer {
15 |
16 | // Definition for a Node.
17 | private static class Node {
18 | int val;
19 | Node next;
20 | Node random;
21 |
22 | public Node(int val) {
23 | this.val = val;
24 | this.next = null;
25 | this.random = null;
26 | }
27 | }
28 |
29 | /**
30 | * 哈希表,key:老节点,value: 新节点
31 | *
32 | * 时间复杂度 O(n), 遍历两遍
33 | * 空间复杂度 O(n),额外的哈希表
34 | */
35 | class Solution {
36 | public Node copyRandomList(Node head) {
37 | Map
21 | * 1.如果为空 或者 是满二叉树,直接可通过公式得到节点个数
22 | * 2.否则,返回左子树节点个数和右子树节点个数,求和得到当前根节点下的节点个数
23 | *
24 | * 时间复杂度:O(log n × log n),深度h=log n,
25 | * 最差情况:只缺最后一个节点就是满二叉树,则每次遍历深度的时间复杂度为 h,h-1,h-2,...,1,加起来是h^2
26 | * 空间复杂度:O(log n)
27 | */
28 | public class CountCompleteTreeNodes0 extends CountCompleteTreeNodes {
29 | @Override
30 | public int countNodes(TreeNode root) {
31 | // 终止条件
32 | if (root == null) {
33 | return 0;
34 | }
35 | TreeNode left = root.left;
36 | TreeNode right = root.right;
37 | int leftDepth = 0;
38 | int rightDepth = 0;
39 | while (left != null) {
40 | left = left.left;
41 | leftDepth++;
42 | }
43 | while (right != null) {
44 | right = right.right;
45 | rightDepth++;
46 | }
47 |
48 | // 说明是满二叉树
49 | if (leftDepth == rightDepth) {
50 | // 注意运算符优先级
51 | return (2 << leftDepth) - 1;
52 | }
53 |
54 | // 非满二叉树
55 | // 本层逻辑
56 | return countNodes(root.left) + countNodes(root.right) + 1;
57 | }
58 | }
59 |
60 |
61 | // TODO 二分查找的方法
62 | // https://leetcode.cn/problems/count-complete-tree-nodes/solution/wan-quan-er-cha-shu-de-jie-dian-ge-shu-by-leetco-2/
63 | }
64 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/DeleteOperationForTwoStrings.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | /**
4 | * LeetCode 583. Delete Operation for Two Strings
5 | * Question: https://leetcode.com/problems/delete-operation-for-two-strings/
6 | * 关键题设: In one step, you can delete exactly one character in either string.
7 | *
8 | * @auther brian
9 | * @since 2022/8/24 23:46
10 | */
11 | public class DeleteOperationForTwoStrings {
12 |
13 | public int minDistance(String word1, String word2) {
14 | return 0;
15 | }
16 |
17 | /**
18 | * 思路1:先根据 1143. Longest Common Subsequence 求最长公共子序列长度lcs
19 | * 然后 word1.len+word2.len- lcs*2 就是结果
20 | *
21 | * dp[i+1][j+1] 表示word1的前0~i个字符 和 word2的前0~j个字符的最长公共自序列的长度
22 | */
23 | public class DeleteOperationForTwoStrings0 extends DeleteOperationForTwoStrings {
24 | @Override
25 | public int minDistance(String word1, String word2) {
26 | int[][] dp = new int[word1.length() + 1][word2.length() + 1];
27 | for (int i = 0; i < word1.length(); i++) {
28 | for (int j = 0; j < word2.length(); j++) {
29 | if (word1.charAt(i) == word2.charAt(j)) {
30 | dp[i + 1][j + 1] = dp[i][j] + 1;
31 | } else {
32 | dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]);
33 | }
34 | }
35 | }
36 | return word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()];
37 | }
38 | }
39 |
40 | // TODO 按正常DP解,不借助最长公共子序列长度lcs
41 | }
42 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/FlattenBinaryTreeToLinkedList.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 114. Flatten Binary Tree to Linked List
7 | * Question: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
8 | * 关键题设: preorder
9 | *
10 | * @auther brian
11 | * @since 2022/12/5 20:51
12 | */
13 | public class FlattenBinaryTreeToLinkedList {
14 |
15 | /**
16 | * 递归解法
17 | */
18 | class Solution {
19 | public void flatten(TreeNode root) {
20 | if (root == null) {
21 | return;
22 | }
23 | recursiveFlatten(root);
24 | }
25 |
26 | /**
27 | * 返回链表的最后一个节点(避免遍历链表)
28 | *
29 | * @param root 非空
30 | * @return 链表的最后一个节点
31 | */
32 | public TreeNode recursiveFlatten(TreeNode root) {
33 | // 叶子节点
34 | if (root.left == null && root.right == null) {
35 | return root;
36 | }
37 |
38 | // flatten左子树
39 | TreeNode leftEnd = null;
40 | if (root.left != null) {
41 | leftEnd = recursiveFlatten(root.left);
42 | }
43 |
44 | // flatten右子树
45 | TreeNode rightEnd = null;
46 | if (root.right != null) {
47 | rightEnd = recursiveFlatten(root.right);
48 | }
49 |
50 | // 更新指向
51 | if (leftEnd != null) {
52 | TreeNode rightStart = root.right;
53 | root.right = root.left;
54 | root.left = null;
55 | leftEnd.right = rightStart;
56 | }
57 |
58 | return rightEnd == null ? leftEnd : rightEnd;
59 |
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/GroupAnagrams.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.HashMap;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | /**
10 | * LeetCode 49. Group Anagrams
11 | * Question: https://leetcode.com/problems/group-anagrams/
12 | * 关键题设: 无
13 | *
14 | * @auther brian
15 | * @since 2022/12/2 22:49
16 | */
17 | public class GroupAnagrams {
18 |
19 | /**
20 | * 排序
21 | */
22 | class Solution0 {
23 | public List
19 | * 对于每个可到达的i, i+nums[i] 就是i这个格子可触达的最远处,和当前最远maxReach取大者即可
20 | * 依次遍历每个可到达的i,不断更新maxReach即可。可到达的含义为:i<=maxReach
21 | *
22 | * 初始化:在第0个格子,maxReach=0+nums[0]
23 | *
24 | * 时间复杂度 O(n)
25 | * 空间复杂度 O(1)
26 | */
27 | public class JumpGame0 extends JumpGame {
28 | @Override
29 | public boolean canJump(int[] nums) {
30 | int maxReach = nums[0];
31 | for (int i = 1; i <= maxReach && i < nums.length; i++) {
32 | maxReach = Math.max(i + nums[i], maxReach);
33 | }
34 | return maxReach >= nums.length - 1;
35 | }
36 | }
37 |
38 | public class JumpGame1 extends JumpGame {
39 | @Override
40 | public boolean canJump(int[] nums) {
41 | int maxReach = 0;
42 | for (int i = 0; i <= maxReach; i++) {
43 | maxReach = Math.max(i + nums[i], maxReach);
44 | if (maxReach >= nums.length - 1) {
45 | return true;
46 | }
47 | }
48 | return maxReach >= nums.length - 1;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/JumpGameII.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | /**
4 | * LeetCode 45. Jump Game II
5 | * Question: https://leetcode.com/problems/jump-game-ii/
6 | * 关键题设: non-negative integers, assume that you can always reach the last index.
7 | *
8 | * @auther brian
9 | * @since 2022/8/10 22:42
10 | */
11 | public class JumpGameII {
12 | public int jump(int[] nums) {
13 | return 0;
14 | }
15 |
16 | /**
17 | * DP?
18 | * 1. dp数组下标及含义:dp[i] 表示到达下标i的最小跳数
19 | * 2. 递推公式:dp[i] = min{dp[j]+1} ,其中 j=i
20 | * 3. dp数组初始化: dp[0]=0, dp[i]=Int.Max
21 | * 4. 遍历顺序:从左到右
22 | */
23 | public class JumpGameII0 extends JumpGameII {
24 | @Override
25 | public int jump(int[] nums) {
26 | int[] dp = new int[nums.length];
27 | dp[0] = 0;
28 | // 初始化
29 | for (int i = 1; i < nums.length; i++) {
30 | dp[i] = Integer.MAX_VALUE;
31 | }
32 |
33 | for (int i = 0; i < nums.length; i++) {
34 | for (int step = 1; step <= nums[i]; step++) {
35 | if (i + step < nums.length) {
36 | dp[i + step] = Math.min(dp[i + step], dp[i] + 1);
37 | }
38 | }
39 | }
40 |
41 | return dp[nums.length - 1];
42 | }
43 | }
44 |
45 | /**
46 | * 贪心
47 | *
48 | * TODO
49 | */
50 | public class JumpGameII1 extends JumpGameII {
51 | @Override
52 | public int jump(int[] nums) {
53 | return super.jump(nums);
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/KthSmallestElementInBST.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * LeetCode 230. Kth Smallest Element in a BST
10 | * Question: https://leetcode.com/problems/kth-smallest-element-in-a-bst/
11 | * 关键题设:无
12 | *
13 | * @auther brian
14 | * @since 2022/5/17 21:45
15 | */
16 | public class KthSmallestElementInBST {
17 | public int kthSmallest(TreeNode root, int k) {
18 | return 0;
19 | }
20 |
21 | /**
22 | * 常规解法:中序遍历BST,到第k个即可。
23 | *
24 | * 中序遍历采用递归实现
25 | */
26 | public static class KthSmallestElementInBST0 extends KthSmallestElementInBST {
27 | @Override
28 | public int kthSmallest(TreeNode root, int k) {
29 | List
21 | * 先构建哈希集合,用于去重;
22 | * 再依次遍历其中的元素num:只统计num-1不在其中时,一直next,看nums++是否在哈希集合中,统计next的次数
23 | * 1)如果num-1在里面,则忽略跳过
24 | * 2)如果num-1不在里面,则每次查看看num是否在里面
25 | *
26 | *
27 | * 时间复杂度:O(n)
28 | * 空间复杂度:O(n)
29 | */
30 | public class LongestConsecutiveSequence0 extends LongestConsecutiveSequence {
31 | @Override
32 | public int longestConsecutive(int[] nums) {
33 | // 构建哈希Set
34 | HashSet
19 | * 1. dp数组以及下标含义:dp[i][j] 表示 s[i...j] 的回文子序列的最大长度
20 | * 2. 递推关系:
21 | * 如果 s[i]==s[j],则 dp[i][j] = dp[i+1][j-1]+2,表示s[i]和s[j]分别作为新的回文子序列的两端
22 | * 如果 s[i]!=s[j],则 dp[i][j] = max{dp[i+1][j],dp[i][j-1]}, 表示取s[i+1...j]和s[i...j-1]的回文子序列长度的较大者
23 | * 3. 初始化:i==j时,dp[i][j]=1
24 | * 4. 遍历顺序:i从大到小,j从小到大,且i<=j,所以只需要上半个矩阵
25 | */
26 | public class LongestPalindromicSubsequence0 extends LongestPalindromicSubsequence {
27 | @Override
28 | public int longestPalindromeSubseq(String s) {
29 | int[][] dp = new int[s.length()][s.length()];
30 | for (int i = s.length() - 1; i >= 0; i--) {
31 | for (int j = i; j < s.length(); j++) {
32 | if (i == j) {
33 | dp[i][j] = 1;
34 | } else if (s.charAt(i) == s.charAt(j)) {
35 | // 即使i+1>j-1时,dp[i + 1][j - 1]=0, 所以dp[i][j]=2,即"aa",i=0,j=1,dp[0][1]=dp[1][0]+2=2这种情况
36 | dp[i][j] = dp[i + 1][j - 1] + 2;
37 | } else {
38 | dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
39 | }
40 | }
41 | }
42 | return dp[0][s.length() - 1];
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LongestSubstringWithoutRepeatingCharacters.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * LeetCode 3. Longest Substring Without Repeating Characters
8 | * Question: https://leetcode.com/problems/longest-substring-without-repeating-characters/
9 | * 关键题设: 无
10 | *
11 | * @auther brian
12 | * @since 2022/11/30 23:37
13 | */
14 | public class LongestSubstringWithoutRepeatingCharacters {
15 |
16 | public int lengthOfLongestSubstring(String s) {
17 | return 0;
18 | }
19 |
20 | /**
21 | * 滑动窗口+hash表
22 | *
23 | * 测试用例:"tmmzuxt"
24 | */
25 | public class LongestSubstringWithoutRepeatingCharacters0 extends LongestSubstringWithoutRepeatingCharacters {
26 | @Override
27 | public int lengthOfLongestSubstring(String s) {
28 | char[] chars = s.toCharArray();
29 | Map
19 | * 1. dp数组下标以及含义:dp[i+1][j+1] 表示nums1数组以下标i结尾,nums2数数组以下标j结尾时,最长重复子数组长度。
20 | * 即 dp[i][j] 表示nums1数组以下标i-1结尾,nums2数数组以下标j-1结尾时,最长重复子数组长度。
21 | * 2. 递推关系:dp[i+1][j+1] = nums1[i]== nums2[j]? dp[i][j]+1 : 0
22 | * 3. 初始化:dp[i][0]=0, dp[0][j]=0
23 | * 4. 遍历顺序:从左到右
24 | */
25 | public static class MaximumLengthOfRepeatedSubarray0 extends MaximumLengthOfRepeatedSubarray {
26 | @Override
27 | public int findLength(int[] nums1, int[] nums2) {
28 | int[][] dp = new int[nums1.length + 1][nums2.length + 1];
29 | int maxLen = 0;
30 | for (int i = 0; i < nums1.length; i++) {
31 | for (int j = 0; j < nums2.length; j++) {
32 | if (nums1[i] == nums2[j]) {
33 | dp[i + 1][j + 1] = dp[i][j] + 1;
34 | }
35 | if (dp[i + 1][j + 1] > maxLen) {
36 | maxLen = dp[i + 1][j + 1];
37 | }
38 | }
39 | }
40 | return maxLen;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/MinStack.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * LeetCode 155. Min Stack
7 | * Question: https://leetcode.com/problems/min-stack/
8 | * 关键题设:in constant time.
9 | *
10 | * @auther brian
11 | * @since 2022/12/11 21:41
12 | */
13 | public class MinStack {
14 |
15 | /**
16 | * 原始栈
17 | */
18 | Stack
16 | * 注意第一排初始化。题设是从最左上 到 最 右下。
17 | */
18 | class Solution {
19 | public int minPathSum(int[][] grid) {
20 | int[] dp = new int[grid[0].length];
21 | // 初始化
22 | dp[0] = grid[0][0];
23 | for (int j = 1; j < grid[0].length; j++) {
24 | dp[j] = dp[j - 1] + grid[0][j];
25 | }
26 |
27 | for (int i = 1; i < grid.length; i++) {
28 | dp[0] = dp[0] + grid[i][0];
29 | for (int j = 1; j < grid[0].length; j++) {
30 | dp[j] = Math.min(dp[j - 1] + grid[i][j], dp[j] + grid[i][j]);
31 | }
32 | }
33 | return dp[grid[0].length - 1];
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/PalindromePartitioning.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.ArrayList;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | /**
8 | * LeetCode 131. Palindrome Partitioning
9 | * Question: https://leetcode.com/problems/palindrome-partitioning/
10 | * 关键题设: 无
11 | *
12 | * @auther brian
13 | * @since 2022/12/5 21:01
14 | */
15 | public class PalindromePartitioning {
16 | /**
17 | * 回溯
18 | *
19 | * 时间复杂度 O(n * 2^n)
20 | * 空间复杂度 O(n) 递归调用栈的高度为 n
21 | */
22 | class Solution {
23 | public List
16 | * 时间复杂度 O(log m*n)
17 | * 空间复杂度 O(1)
18 | */
19 | class Solution {
20 | public boolean searchMatrix(int[][] matrix, int target) {
21 | // index: 0~m*n
22 | int m = matrix.length;
23 | int n = matrix[0].length;
24 | int left = 0;
25 | int right = m * n - 1;
26 | while (left <= right) {
27 | int mid = (left + right) / 2;
28 | if (getValue(matrix, mid, n) == target) {
29 | return true;
30 | } else if (getValue(matrix, mid, n) < target) {
31 | left = mid + 1;
32 | } else {
33 | right = mid - 1;
34 | }
35 | }
36 | return false;
37 | }
38 |
39 | private int getValue(int[][] matrix, int index, int n) {
40 | int i = index / n;
41 | int j = index % n;
42 | return matrix[i][j];
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/SetMatrixZeroes.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | /**
9 | * LeetCode 73. Set Matrix Zeroes
10 | * Question: https://leetcode.com/problems/set-matrix-zeroes/
11 | * 关键题设: 无
12 | *
13 | * @auther brian
14 | * @since 2022/12/5 19:36
15 | */
16 | public class SetMatrixZeroes {
17 | /**
18 | * 非最优解, m*n的矩阵
19 | *
20 | * 时间复杂度 O(m*n)
21 | * 空间复杂度 O(m+n)
22 | */
23 | class Solution {
24 | public void setZeroes(int[][] matrix) {
25 | Map
19 | * 维护两个指针:
20 | * p0表示 [0,p0)下标范围全是0
21 | * p2表示 (p2,n-1]下标范围全是2
22 | * 初始化: p0=0, p2=n-1, 这样两个区间范围初始都是空
23 | *
24 | * 依次遍历i,
25 | * - 遇到0就交换nums[i]和nums[p0],同时,p0 和 i 都向后移一位(因为一定有i>=p0, 所以此时i指向的是之前的nums[p0],且一定遇到过,不可能是2,无论是1还是0,都无需再次判断)
26 | * - 遇到2就交换nums[i]和nums[p2],只 p2 向前移一位,i不动(因为交换后,i指向的是之前的nums[p2],值未知,可能为0,需要再次判断,故i不能++)
27 | * - 遇到1就不需要交换,i 向后移一位
28 | * 当i>p2,结束遍历
29 | */
30 | public class SortColors0 extends SortColors {
31 | @Override
32 | public void sortColors(int[] nums) {
33 | int p0 = 0;
34 | int p2 = nums.length - 1;
35 | for (int i = 0; i <= p2; ) {
36 | if (nums[i] == 0) {
37 | swap(nums, i, p0);
38 | p0++;
39 | i++;
40 | } else if (nums[i] == 2) {
41 | swap(nums, i, p2);
42 | p2--;
43 | // i 不移动
44 | } else {
45 | i++;
46 | }
47 | }
48 | }
49 |
50 | private void swap(int[] nums, int i, int j) {
51 | int temp = nums[i];
52 | nums[i] = nums[j];
53 | nums[j] = temp;
54 | }
55 |
56 | }
57 |
58 | // TODO 补充其他解法
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/Subsets.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.ArrayList;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | /**
8 | * LeetCode 78. Subsets
9 | * Question: https://leetcode.com/problems/subsets/
10 | * 关键题设: 无
11 | *
12 | * @auther brian
13 | * @since 2022/12/5 20:07
14 | */
15 | public class Subsets {
16 |
17 | /**
18 | * 回溯
19 | */
20 | class Solution {
21 | public List
20 | * BST节点个数为i时的结构数记为 dp[i], 则dp[i]= ∑ 根节点为j的结构数, j依次取i个节点的每一个。
21 | * 当根节点为j (1<=j<=i)时,假设小于j的有l个节点,大于j的有r个节点
22 | * 则左子树就是这l个节点构成的BST,右子树就是这r个节点构成的BST,且l+r+1=i
23 | * 所以 当根节点为j时的结构数=dp[l]*dp[r]
24 | * 当j依次取i个节点中的每一个节点,l和r会分别依次 +1 和 -1。
25 | * 将这些 dp[l]*dp[r] 求和,即可得到 dp[i]
26 | *
27 | * 搜索二叉树的特点:左子树的所有节点小于根节点,左子树的所有节点大于根节点
28 | *
29 | * 例子:
30 | * dp[0] = 1 表示子树为空的情况
31 | * dp[1] = 1 可以直观看出,也由 dp[0]*dp[0] 推导出。写代码时注意不要重复计算 dp[1]
32 | * dp[2] = dp[0]*dp[1] + dp[1]*dp[0];
33 | * dp[3] = dp[0]*dp[2] + dp[1]+dp1[1] + dp[2]*dp[0]
34 | *
35 | *
36 | * 时间复杂度 O(n^2)
37 | * 空间复杂度 O(n), 由于递推关系中,历史所有规模的子问题都需要记录,所以没法简化了。
38 | */
39 | public class UniqueBinarySearchTrees0 extends UniqueBinarySearchTrees {
40 | @Override
41 | public int numTrees(int n) {
42 | int[] dp = new int[n + 1];
43 | dp[0] = 1;
44 | // dp[1] = 1; // i从1循环则不需要
45 | for (int i = 1; i <= n; i++) {
46 | for (int l = 0; l < i; l++) {
47 | // 右子树节点个数 r = i - 1 - l
48 | dp[i] = dp[i] + dp[l] * dp[i - 1 - l];
49 | }
50 | }
51 | return dp[n];
52 | }
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/ValidateBinarySearchTree.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | /**
6 | * LeetCode 98. Validate Binary Search Tree
7 | * Question https://leetcode.com/problems/validate-binary-search-tree/
8 | * 关键题设:无
9 | *
10 | * @auther brian
11 | * @since 2022/9/7 22:14
12 | */
13 | public class ValidateBinarySearchTree {
14 | public boolean isValidBST(TreeNode root) {
15 | return false;
16 | }
17 |
18 | /**
19 | * 递归
20 | *
21 | * 注意:不是只比较每一层的cur > left,cur < right就完了
22 | * 需要 cur> any of left, cur < any of right
23 | *
24 | * 时间复杂度:O(n)
25 | * 空间复杂度:O(n), 递归用到了栈
26 | */
27 | public class ValidateBinarySearchTree0 extends ValidateBinarySearchTree {
28 | @Override
29 | public boolean isValidBST(TreeNode root) {
30 | return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
31 | }
32 |
33 | /**
34 | * 判断root是否在区间 (min, max) 内,左开右开
35 | * 因为测试数据范围是可能到 Integer.MIN_VALUE 和 Integer.MAX_VALUE,所以这里用long
36 | *
37 | * @param root 当前节点
38 | * @param min 下限
39 | * @param max 上限
40 | * @return 是否BST
41 | */
42 | public boolean isValidBST(TreeNode root, long min, long max) {
43 | if (root == null) {
44 | return true;
45 | }
46 |
47 | if (root.val <= min || root.val >= max) {
48 | return false;
49 | }
50 |
51 | return isValidBST(root.left, min, root.val)
52 | && isValidBST(root.right, root.val, max);
53 | }
54 | }
55 |
56 | // TODO 中序遍历,递归/迭代, 然后检查数组是否递增即可
57 | // 中序遍历可以加一个pre指针,表示上一次访问的节点
58 | // https://leetcode.cn/problems/validate-binary-search-tree/solution/zhong-xu-bian-li-qing-song-na-xia-bi-xu-miao-dong-/
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/WiggleSubsequence.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | /**
4 | * LeetCode 376. Wiggle Subsequence
5 | * Question: https://leetcode.com/problems/wiggle-subsequence/
6 | * 关键题设: 无
7 | *
8 | * @auther brian
9 | * @since 2022/8/11 23:14
10 | */
11 | public class WiggleSubsequence {
12 |
13 | public int wiggleMaxLength(int[] nums) {
14 | return 0;
15 | }
16 |
17 | /**
18 | * 贪心
19 | * len表示 wiggleMaxLength
20 | * 当前基准数cur
21 | * 上一次趋势lastTrend, 小于0表示递减,大于0表示递增,
22 | * 遇到同趋势的就忽略,并更新cur; 遇到不同趋势的,则len+1, 并更新cur
23 | *
24 | * 注意:
25 | * 上一次趋势的初始化问题需要注意!
26 | *
27 | * 边界情况:
28 | * [3,3,3,2,5]
29 | */
30 | public class WiggleSubsequence0 extends WiggleSubsequence {
31 | @Override
32 | public int wiggleMaxLength(int[] nums) {
33 | int len = 1;
34 | int cur = nums[0];
35 | int lastTrend = 0; // 假设 下标-1的元素和 nums[0]一样
36 | int trend = 0;
37 |
38 | for (int i = 1; i < nums.length; i++) {
39 | trend = nums[i] - cur;
40 |
41 | // 当Wiggle Subsequence内只有一个元素时,不管递增还是递减,只要不是相等,都len+1
42 | if (len == 1 && trend != 0) {
43 | len++;
44 | }
45 | if ((trend > 0 && lastTrend < 0) || (trend < 0 && lastTrend > 0)) {
46 | len++;
47 | }
48 |
49 | cur = nums[i];
50 | if (trend != 0) {
51 | lastTrend = trend;
52 | }
53 |
54 | }
55 | return len;
56 | }
57 | }
58 |
59 | // TODO 用DP解
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/WordBreak.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * LeetCode 139. Word Break
7 | * Question: https://leetcode.com/problems/word-break/
8 | * 关键题设: 无
9 | *
10 | * @auther brian
11 | * @since 2022/7/11 21:19
12 | */
13 | public class WordBreak {
14 |
15 | public boolean wordBreak(String s, List
22 | * 1. dp数组下标及含义:dp[j] 表示用字典里的词能否匹配到s中从开头开始长度为j的字符
23 | * 2. 递推关系:
24 | * 如果 s[0...j-1] 以wordDict中的某个单词word结尾,则dp[j] = dp[j-word.length] || dp[j]
25 | * (这里用 或,而不是直接dp[j] = dp[j-word.length],是因为任一匹配即可,不能因为某次以单词word结尾,但dp[j-word.length]=false 而导致dp[j]被覆盖为false,
26 | * 应该只要匹配过一次true就算true)
27 | * 否则 dp[j] = false
28 | *
29 | * 3. 初始化: dp[0] = true,表示s长度为0时默认匹配。很关键
30 | * 4. 遍历顺序:外层j,从左到右,内层 wordDict。
31 | */
32 | public static class WordBreak0 extends WordBreak {
33 | @Override
34 | public boolean wordBreak(String s, List> levelOrderBottom(TreeNode root) {
17 | return null;
18 | }
19 |
20 | // TODO 练手复习
21 | }
22 |
--------------------------------------------------------------------------------
/algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/BinaryTreeRightSideView.java:
--------------------------------------------------------------------------------
1 | package com.brianway.learning.algorithms.leetcode.medium;
2 |
3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode;
4 |
5 | import java.util.ArrayList;
6 | import java.util.LinkedList;
7 | import java.util.List;
8 | import java.util.Queue;
9 |
10 | /**
11 | * LeetCode 199. Binary Tree Right Side View
12 | * Question: https://leetcode.com/problems/binary-tree-right-side-view/
13 | * 关键题设:无
14 | *
15 | * @auther brian
16 | * @since 2022/9/2 21:53
17 | */
18 | public class BinaryTreeRightSideView {
19 | public List
> combinationSum3(int k, int n) {
17 | return null;
18 | }
19 |
20 | /**
21 | * 回溯+剪枝
22 | */
23 | public class CombinationSumIII0 extends CombinationSumIII {
24 | @Override
25 | public List
> combinationSum3(int k, int n) {
26 | List
> result = new ArrayList<>();
27 | backtracking(result, new LinkedList<>(), 0, n, k, 1);
28 | return result;
29 | }
30 |
31 | /**
32 | * @param result 满足条件的所有结果
33 | * @param path 单个结果的路径
34 | * @param pathSum 单个路径和
35 | * @param n n
36 | * @param k k
37 | * @param startIndex 本层的一个数
38 | */
39 | public void backtracking(List
> result, LinkedList
> groupAnagrams(String[] strs) {
24 | Map
> partition(String s) {
24 | List
> result = new ArrayList<>();
25 | char[] charArr = s.toCharArray();
26 | backtracking(result, new LinkedList
> result, LinkedList
> permute(int[] nums) {
19 | return null;
20 | }
21 |
22 | /**
23 | * 回溯
24 | */
25 | public class Permutations0 extends Permutations {
26 | @Override
27 | public List
> permute(int[] nums) {
28 | List
> result = new ArrayList<>();
29 | List
> result, LinkedList
> subsets(int[] nums) {
22 | List
> result = new ArrayList<>();
23 | backtracking(result, new LinkedList<>(), nums, 0);
24 | return result;
25 | }
26 |
27 | public void backtracking(List
> result, LinkedList
> triangle = transform(a);
27 | //System.out.println(triangle);
28 | Assert.assertEquals(result, testObject.minimumTotal(triangle));
29 | }
30 |
31 | private List
> transform(int[][] a) {
32 | List
> triangle = new ArrayList<>();
33 | if (a == null) {
34 | return triangle;
35 | }
36 | List