├── .gitignore ├── lab-09 ├── pom.xml ├── src │ └── main │ │ └── java │ │ └── cn │ │ └── iocoder │ │ └── springboot │ │ └── labs │ │ └── lab09 │ │ ├── graph │ │ ├── DijkstraTest.java │ │ └── Graph.java │ │ ├── leetcode │ │ ├── no0035 │ │ │ ├── Main.java │ │ │ ├── Solution01.java │ │ │ └── Solution02.java │ │ ├── no0036 │ │ │ ├── Solution01.java │ │ │ └── Solution02.java │ │ ├── no0072 │ │ │ └── Solution.java │ │ ├── no0120 │ │ │ ├── Solution01.java │ │ │ └── Solution02.java │ │ ├── no0123 │ │ │ └── Solution.java │ │ ├── no0146 │ │ │ ├── LRUCache.java │ │ │ └── LRUCache02.java │ │ ├── no0152 │ │ │ ├── Solution01.java │ │ │ ├── Solution02.java │ │ │ └── Solution03.java │ │ ├── no0208 │ │ │ └── Trie.java │ │ ├── no0231 │ │ │ └── Solution01.java │ │ ├── no0235 │ │ │ ├── Solution01.java │ │ │ ├── Solution02.java │ │ │ ├── Solution03.java │ │ │ └── TreeNode.java │ │ ├── no0300 │ │ │ ├── Solution01.java │ │ │ └── Solution02.java │ │ ├── no0703 │ │ │ ├── KthLargest.java │ │ │ └── KthLargest2.java │ │ └── package-info.java │ │ ├── linkedlist │ │ └── HuiWenLinkedListTest.java │ │ ├── match │ │ └── RabinKarp.java │ │ ├── search │ │ ├── SkipList.java │ │ ├── SkipList2.java │ │ ├── SkipListTest.java │ │ └── SquareTest.java │ │ ├── sort │ │ ├── BucketSorterTest.java │ │ ├── HeapSorterTest.java │ │ ├── MergeSorterTest.java │ │ ├── QuickSorterTest.java │ │ ├── RadixSorterTest.java │ │ └── TheFirstBigKTest.java │ │ └── tree │ │ └── MySQLBTreePlusTest.java └── 准备删除 ├── pom.xml └── src └── main └── java └── cn └── iocoder └── algorithm ├── daimamianshizhinan ├── p317 │ └── Solution.java └── package-info.java └── leetcode ├── common ├── ListNode.java ├── Node.java └── TreeNode.java ├── no0001 ├── Solution.java └── Solution02.java ├── no0002 ├── ListNode.java └── Solution.java ├── no0003 ├── Solution.java └── Solution02.java ├── no0004 └── Solution.java ├── no0008 └── Solution.java ├── no0009 └── Solution.java ├── no0010 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0011 └── Solution.java ├── no0015 ├── Solution.java └── Solution02.java ├── no0016 └── Solution.java ├── no0017 ├── Solution.java └── Solution02.java ├── no0018 └── Solution.java ├── no0019 └── Solution.java ├── no0020 └── Solution.java ├── no0021 └── Solution.java ├── no0022 └── Solution.java ├── no0023 ├── Solution.java └── Solution02.java ├── no0024 ├── ListNode.java ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0025 ├── ListNode.java └── Solution.java ├── no0026 └── Solution.java ├── no0027 ├── Solution.java └── Solution02.java ├── no0028 └── Solution.java ├── no0033 └── Solution.java ├── no0034 ├── Solution.java └── Solution02.java ├── no0035 └── Solution.java ├── no0037 └── Solution.java ├── no0039 └── Solution.java ├── no0040 └── Solution.java ├── no0042 ├── Solution.java └── Solution02.java ├── no0045 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0046 └── Solution.java ├── no0047 └── Solution.java ├── no0049 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0050 ├── Solution.java └── Solution02.java ├── no0051 └── Solution.java ├── no0052 ├── Solution01.java ├── Solution011.java └── Solution02.java ├── no0053 ├── Solution.java └── SolutionX.java ├── no0054 └── Solution.java ├── no0055 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0061 ├── Solution.java └── Solution02.java ├── no0062 └── Solution.java ├── no0063 └── Solution.java ├── no0064 └── Solution.java ├── no0069 ├── Solution.java └── Solution02.java ├── no0070 ├── Solution.java └── SolutionX.java ├── no0073 └── Solution.java ├── no0074 ├── Solution.java └── Solution02.java ├── no0075 └── Solution.java ├── no0076 ├── Solution.java └── Solution02.java ├── no0077 ├── Solution.java └── SolutionX.java ├── no0078 └── Solution.java ├── no0079 └── Solution.java ├── no0080 ├── Solution.java └── Solution02.java ├── no0081 └── Solution.java ├── no0082 └── Solution.java ├── no0083 └── Solution.java ├── no0084 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0085 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0086 └── Solution.java ├── no0088 └── Solution.java ├── no0090 └── Solution.java ├── no0091 └── Solution.java ├── no0092 ├── ListNode.java ├── Solution.java └── Solution02.java ├── no0093 └── Solution.java ├── no0094 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0095 ├── Solution.java └── Solution02.java ├── no0096 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0098 ├── Solution.java └── Solution01.java ├── no0099 └── Solution.java ├── no0100 └── Solution.java ├── no0101 ├── Solution.java └── Solution02.java ├── no0102 └── Solution.java ├── no0104 └── Solution.java ├── no0107 └── Solution.java ├── no0108 └── Solution.java ├── no0109 ├── Solution.java └── Solution02.java ├── no0110 └── Solution.java ├── no0111 ├── Solution.java └── Solution02.java ├── no0112 ├── Solution.java └── Solution02.java ├── no0113 ├── Solution.java └── Solution02.java ├── no0118 └── Solution.java ├── no0119 └── Solution.java ├── no0121 └── Solution.java ├── no0122 ├── Solution.java └── Solution02.java ├── no0123 ├── Solution.java └── Solution02.java ├── no0124 └── Solution.java ├── no0125 └── Solution.java ├── no0126 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0127 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0128 ├── Solution.java ├── Solution011.java └── Solution02.java ├── no0129 └── Solution.java ├── no0130 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0131 └── Solution.java ├── no0133 ├── Node.java └── Solution.java ├── no0136 └── Solution.java ├── no0138 └── Solution.java ├── no0139 └── Solution.java ├── no0141 ├── ListNode.java ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0142 ├── ListNode.java └── Solution.java ├── no0144 ├── Solution.java └── Solution02.java ├── no0145 ├── Solution.java └── Solution02.java ├── no0147 ├── Solution.java └── Solution02.java ├── no0148 ├── ListNode.java └── Solution.java ├── no0151 └── Solution.java ├── no0152 └── Solution.java ├── no0153 └── Solution.java ├── no0154 └── Solution.java ├── no0155 ├── MinStack.java └── MinStack02.java ├── no0159 ├── Solution.java └── Solution02.java ├── no0160 └── Solution.java ├── no0162 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0167 └── Solution.java ├── no0169 ├── Solution.java └── Solution02.java ├── no0188 └── Solution.java ├── no0189 ├── Solution.java └── Solution02.java ├── no0190 └── Solution.java ├── no0191 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0198 └── Solution.java ├── no0200 ├── Solution.java └── Solution02.java ├── no0205 └── Solution.java ├── no0206 ├── ListNode.java ├── Solution.java └── Solution02.java ├── no0207 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0208 └── Trie.java ├── no0210 └── Solution.java ├── no0212 ├── Solution.java └── Solution02.java ├── no0213 ├── Solution.java └── Solution02.java ├── no0215 ├── Solution.java ├── Solution020.java ├── Solution021.java ├── Solution022.java ├── Solution03.java └── Solution04.java ├── no0216 └── Solution.java ├── no0217 └── Solution.java ├── no0219 └── Solution.java ├── no0220 ├── Solution.java ├── Solution011.java ├── Solution012.java └── Solution02.java ├── no0221 └── Solution.java ├── no0225 └── MyStack.java ├── no0229 ├── Solution.java └── Solution02.java ├── no0230 └── Solution.java ├── no0231 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0232 └── MyQueue.java ├── no0234 └── Solution.java ├── no0235 ├── Solution.java └── Solution02.java ├── no0236 ├── Solution.java └── Solution02.java ├── no0238 └── Solution.java ├── no0239 ├── Solution.java └── Solution02.java ├── no0240 └── Solution.java ├── no0241 └── Solution.java ├── no0242 └── Solution.java ├── no0257 └── Solution.java ├── no0260 └── Solution.java ├── no0266 └── Solution.java ├── no0268 └── Solution.java ├── no0278 ├── Solution.java └── VersionControl.java ├── no0279 ├── Solution.java └── Solution02.java ├── no0282 ├── Solution.java └── Solution02.java ├── no0283 ├── Solution.java └── Solution02.java ├── no0287 ├── Solution01.java ├── Solution02.java └── Solution03.java ├── no0290 └── Solution.java ├── no0297 ├── Codec.java └── Codec02.java ├── no0301 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0303 ├── NumArray.java └── NumArray02.java ├── no0309 └── Solution.java ├── no0318 └── Solution.java ├── no0322 └── Solution.java ├── no0328 └── Solution.java ├── no0337 ├── Solution.java └── Solution02.java ├── no0338 ├── Solution.java └── Solution01.java ├── no0340 └── Solution.java ├── no0342 └── Solution.java ├── no0343 ├── Solution.java ├── Solution02.java └── SolutionX.java ├── no0344 └── Solution.java ├── no0345 └── Solution.java ├── no0347 └── Solution.java ├── no0367 └── Solution.java ├── no0371 └── Solution.java ├── no0377 └── Solution.java ├── no0378 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0387 └── Solution.java ├── no0392 ├── Solution.java └── SolutionX.java ├── no0394 ├── Solution.java └── Solution02.java ├── no0404 └── Solution.java ├── no0406 └── Solution.java ├── no0409 └── Solution.java ├── no0413 ├── Solution.java └── Solution02.java ├── no0417 ├── Solution.java └── Solution02.java ├── no0429 └── Solution.java ├── no0433 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0435 ├── Solution.java ├── Solution02.java └── SolutionX.java ├── no0437 ├── Solution.java └── Solution02.java ├── no0438 └── Solution.java ├── no0442 └── Solution.java ├── no0445 ├── ListNode.java └── Solution.java ├── no0448 └── Solution.java ├── no0449 ├── Codec.java └── Codec2.java ├── no0450 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0451 └── Solution.java ├── no0452 └── Solution.java ├── no0454 └── Solution.java ├── no0455 └── Solution.java ├── no0461 └── Solution.java ├── no0474 └── Solution.java ├── no0476 ├── Solution.java └── Solution02.java ├── no0485 └── Solution.java ├── no0494 ├── Solution.java └── Solution02.java ├── no0496 └── Solution.java ├── no0501 └── Solution.java ├── no0503 ├── Solution.java └── Solution02.java ├── no0508 ├── Solution.java └── Solution02.java ├── no0509 ├── Solution.java └── SolutionX.java ├── no0513 ├── Solution.java └── Solution02.java ├── no0518 └── Solution.java ├── no0524 └── Solution.java ├── no0530 └── Solution.java ├── no0538 └── Solution.java ├── no0540 ├── Solution.java └── Solution02.java ├── no0542 ├── Solution.java ├── Solution02.java ├── Solution03.java └── Solution04.java ├── no0543 └── Solution.java ├── no0547 ├── Solution.java └── Solution02.java ├── no0556 └── Solution.java ├── no0557 └── Solution.java ├── no0565 └── Solution.java ├── no0566 └── Solution.java ├── no0572 └── Solution.java ├── no0589 ├── Solution.java └── Solution02.java ├── no0590 └── Solution.java ├── no0594 └── Solution.java ├── no0605 └── Solution.java ├── no0617 └── Solution.java ├── no0633 └── Solution.java ├── no0637 ├── Solution.java └── Solution02.java ├── no0645 └── Solution.java ├── no0653 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0665 └── Solution.java ├── no0666 └── Solution.java ├── no0667 └── Solution.java ├── no0669 └── Solution.java ├── no0671 └── Solution.java ├── no0675 ├── Solution.java └── Solution02.java ├── no0677 └── MapSum.java ├── no0680 └── Solution.java ├── no0684 └── Solution.java ├── no0685 └── Solution.java ├── no0687 ├── Solution.java └── Solution02.java ├── no0693 └── Solution.java ├── no0695 └── Solution.java ├── no0696 └── Solution.java ├── no0697 └── Solution.java ├── no0700 └── Solution.java ├── no0701 ├── Solution.java └── Solution02.java ├── no0704 └── Solution.java ├── no0707 └── MyLinkedList.java ├── no0714 ├── Solution.java └── Solution02.java ├── no0716 ├── MaxStack.java └── MaxStack02.java ├── no0725 └── Solution.java ├── no0726 └── Solution.java ├── no0733 └── Solution.java ├── no0739 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0744 └── Solution.java ├── no0746 └── Solution.java ├── no0752 └── Solution.java ├── no0763 ├── Solution.java └── Solution02.java ├── no0766 └── Solution.java ├── no0768 └── Solution.java ├── no0769 └── Solution.java ├── no0776 ├── Solution.java └── Solution02.java ├── no0784 ├── Solution.java └── Solution02.java ├── no0785 ├── Solution.java └── Solution02.java ├── no0802 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0814 ├── Solution.java └── Solution02.java ├── no0827 └── Solution.java ├── no0841 └── Solution.java ├── no0842 ├── Solution.java └── Solution02.java ├── no0852 ├── Solution.java └── Solution02.java ├── no0856 └── Solution.java ├── no0872 └── Solution.java ├── no0934 └── Solution.java ├── no0965 └── Solution.java ├── no0981 ├── TimeMap.java └── TimeMap02.java ├── no0987 ├── Solution.java └── Solution02.java ├── no0996 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no0997 ├── Solution.java ├── Solution02.java └── Solution03.java ├── no1003 └── Solution.java └── text /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.ipr 22 | *.iws 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | target 27 | -------------------------------------------------------------------------------- /lab-09/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | labs-parent 7 | cn.iocoder.springboot.labs 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | lab-09 13 | 14 | 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0035/Main.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0035; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | // new Solution01().solveNQueens(4); 7 | new Solution02().solveNQueens(4); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0146/LRUCache.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0146; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | public class LRUCache { 7 | 8 | private Map cache; 9 | 10 | public LRUCache(int capacity) { 11 | this.cache = new LinkedHashMap((int) Math.ceil(capacity / 0.75f) + 1, 0.75f, true) { 12 | 13 | @Override 14 | protected boolean removeEldestEntry(Map.Entry eldest) { 15 | return size() > capacity; 16 | } 17 | 18 | }; 19 | } 20 | 21 | public int get(int key) { 22 | Integer val = cache.get(key); 23 | return val != null ? val : -1; 24 | } 25 | 26 | public void put(int key, int value) { 27 | cache.put(key, value); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0231/Solution01.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0231; 2 | 3 | public class Solution01 { 4 | 5 | public boolean isPowerOfTwo(int n) { 6 | // 非正整数,非正整数 7 | if (n <= 0) { 8 | return false; 9 | } 10 | 11 | int mask = 1; 12 | for (int i = 0; i < 32; i++) { 13 | // 或运算,如果就是自己,说明是 2 的 n 次方 14 | if ((n | mask) == mask) { 15 | return true; 16 | } 17 | 18 | // mask 超过范围,说明就是不符合 19 | if (mask > n) { 20 | return false; 21 | } 22 | 23 | mask = mask << 1; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | public static void main(String[] args) { 30 | Solution01 solution = new Solution01(); 31 | System.out.println(solution.isPowerOfTwo(1)); 32 | System.out.println(solution.isPowerOfTwo(2)); 33 | System.out.println(solution.isPowerOfTwo(3)); 34 | System.out.println(solution.isPowerOfTwo(4)); 35 | System.out.println(solution.isPowerOfTwo(5)); 36 | System.out.println(solution.isPowerOfTwo(6)); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0235/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0235; 2 | 3 | /** 4 | * 递归求解父节点 5 | */ 6 | public class Solution02 { 7 | 8 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 9 | if (p.val < root.val 10 | && root.val > q.val) { // 因为 root.val 大于 q.val ,说明 root 的值过大,需要往左走 11 | return lowestCommonAncestor(root.left, p, q); 12 | } else if (p.val > root.val // 因为 root.val 小于 p.val ,说明 root 的值过小,需要往右走 13 | && root.val < q.val) { 14 | return lowestCommonAncestor(root.right, p, q); 15 | } else { // 其他情况,root 都是符合条件的,例如说 root 的泛微在 p and q 之间(或者 q and p 之间)。 16 | // 为什么直接返回 root 就可以,因为如果不是最接近的父节点,p 和 q 要么在其左边,要么在其右边。 17 | return root; 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0235/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0235; 2 | 3 | /** 4 | * {@link Solution02} 的改进,非递归方式。 5 | */ 6 | public class Solution03 { 7 | 8 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 9 | while (true) { 10 | if (p.val < root.val 11 | && root.val > q.val) { // 因为 root.val 大于 q.val ,说明 root 的值过大,需要往左走 12 | root = root.left; 13 | } else if (p.val > root.val // 因为 root.val 小于 p.val ,说明 root 的值过小,需要往右走 14 | && root.val < q.val) { 15 | root = root.right; 16 | } else { // 其他情况,root 都是符合条件的,例如说 root 的泛微在 p and q 之间(或者 q and p 之间)。 17 | return root; 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0235/TreeNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0235; 2 | 3 | public class TreeNode { 4 | 5 | int val; 6 | TreeNode left; 7 | TreeNode right; 8 | 9 | TreeNode(int x) { val = x; } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/no0300/Solution01.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.leetcode.no0300; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * DP 实现,时间复杂度为 O(N^2) 。 7 | * 8 | * DP 转换方程是: 9 | * dp[i] = MAX(dp[i], dp[j] + 1) 10 | * 其中,dp[i] 表示,截止目前,最大的上升的子序列 11 | */ 12 | public class Solution01 { 13 | 14 | public int lengthOfLIS(int[] nums) { 15 | if (nums.length == 0) { 16 | return 0; 17 | } 18 | 19 | int[] dps = new int[nums.length]; 20 | Arrays.fill(dps, 1); // 都赋值为 1 先,因为自己是自己的递增。 21 | int result = 1; 22 | 23 | // dp 24 | for (int i = 1; i < nums.length; i++) { 25 | for (int j = 0; j < i; j++) { 26 | if (nums[i] > nums[j]) { 27 | dps[i] = Math.max(dps[i], dps[j] + 1); 28 | } 29 | } 30 | result = Math.max(result, dps[i]); 31 | } 32 | 33 | return result; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/leetcode/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * leetcode 题目解答 3 | */ 4 | package cn.iocoder.springboot.labs.lab09.leetcode; 5 | -------------------------------------------------------------------------------- /lab-09/src/main/java/cn/iocoder/springboot/labs/lab09/search/SquareTest.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.springboot.labs.lab09.search; 2 | 3 | /** 4 | * 使用二分查找,计算平方根。 5 | */ 6 | public class SquareTest { 7 | 8 | public static void main(String[] args) { 9 | double result = sqrt(5, 0.00001D); 10 | System.out.println(result); 11 | } 12 | 13 | // precision 表示精度 14 | private static double sqrt(int number, double precision) { 15 | int rounds = 0; // 用于记录轮次,调试用途 16 | double low = 0; 17 | double high = number; 18 | while (low <= high) { 19 | double middle = low + ((high - low) / 2); 20 | double result = middle * middle; 21 | System.out.println(String.format("第 %d 轮,结果:%f", ++rounds, middle)); 22 | 23 | double diff = number - result; 24 | if (0 <= diff && diff <= precision) { 25 | return middle; 26 | } 27 | if (result < number) { 28 | low = middle; 29 | } else if (result > number) { 30 | high = middle; 31 | } else { 32 | throw new IllegalStateException("不可能出现"); 33 | } 34 | } 35 | throw new IllegalStateException("必然有结果,还能求不出平方根"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lab-09/准备删除: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YunaiV/algorithm1024/e5a963d3efef33ca3e6cc86e33fc10f5665b8a4c/lab-09/准备删除 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.iocoder.algorithm 8 | algorithm1024 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | lab-09 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/daimamianshizhinan/p317/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.daimamianshizhinan.p317; 2 | 3 | /** 4 | * https://www.nowcoder.com/practice/1827258942284b2abfe65809785ac91a 5 | * 6 | * 不用额外变量交换两个整数的值 7 | */ 8 | public class Solution { 9 | 10 | public void swap(int a, int b) { 11 | a = a ^ b; 12 | b = a ^ b; 13 | a = b ^ a; 14 | 15 | System.out.println("a :" + a); 16 | System.out.println("b :" + b); 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution solution = new Solution(); 21 | solution.swap(2, 3); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/daimamianshizhinan/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 程序员代码面试指南 3 | */ 4 | package cn.iocoder.algorithm.daimamianshizhinan; 5 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/common/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.common; 2 | 3 | public class ListNode { 4 | 5 | public int val; 6 | 7 | public ListNode next; 8 | 9 | public ListNode(int x) { 10 | val = x; 11 | next = null; 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "ListNode{" + 17 | "val=" + val + 18 | '}'; 19 | } 20 | 21 | public static ListNode create(int... args) { 22 | if (args.length == 0) { 23 | return null; 24 | } 25 | ListNode dummy = new ListNode(0); 26 | ListNode current = dummy; 27 | for (int arg : args) { 28 | current.next = new ListNode(arg); 29 | current = current.next; 30 | } 31 | return dummy.next; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/common/Node.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.common; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 多节点 7 | */ 8 | public class Node { 9 | 10 | public int val; 11 | public List children; 12 | 13 | public Node(int val) { 14 | this.val = val; 15 | } 16 | 17 | public Node(int val, List children) { 18 | this.val = val; 19 | this.children = children; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0001/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0001; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 暴力法 7 | * 8 | * https://leetcode-cn.com/problems/two-sum/ 9 | */ 10 | public class Solution { 11 | 12 | public int[] twoSum(int[] nums, int target) { 13 | for (int i = 0; i < nums.length; i++) { 14 | for (int j = i + 1; j < nums.length; j++) { 15 | if (nums[i] + nums[j] == target) { 16 | return new int[]{i, j}; 17 | } 18 | } 19 | } 20 | 21 | return new int[]{-1, -1}; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | System.out.println(Arrays.toString(solution.twoSum(new int[]{2, 7, 11, 15}, 9))); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0001/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0001; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * 一遍哈希 9 | */ 10 | public class Solution02 { 11 | 12 | public int[] twoSum(int[] nums, int target) { 13 | Map numIndexMap = new HashMap(nums.length, 1.0F); 14 | for (int i = 0; i < nums.length; i++) { 15 | // 判断是否有匹配的 16 | Integer j = numIndexMap.get(target - nums[i]); 17 | if (j != null) { 18 | return new int[]{i, j}; 19 | } 20 | 21 | // 添加到 numIndexMap 中 22 | numIndexMap.put(nums[i], i); 23 | } 24 | 25 | return new int[]{-1, -1}; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(Arrays.toString(solution.twoSum(new int[]{2, 7, 11, 15}, 9))); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0002/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0002; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0003/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0003; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 8 | */ 9 | public class Solution { 10 | 11 | public int lengthOfLongestSubstring(String s) { 12 | if (s == null || s.length() == 0) { 13 | return 0; 14 | } 15 | 16 | // 初始化一堆遍历,默认使用第一个字符 17 | int begin = 0; 18 | int max = 1; 19 | Map characterIndexes = new HashMap<>(); 20 | characterIndexes.put(s.charAt(0), 0); 21 | 22 | for (int i = 1; i < s.length(); i++) { 23 | Integer index = characterIndexes.get(s.charAt(i)); 24 | // 已经存在 25 | if (index != null && index >= begin) { 26 | begin = index + 1; 27 | } else { 28 | max = Math.max(max, i - begin + 1); 29 | } 30 | characterIndexes.put(s.charAt(i), i); 31 | } 32 | 33 | return max; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0003/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0003; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 在 {@link Solution} 的基础上,将 Map 改成数组,因为字母有限 7 | */ 8 | public class Solution02 { 9 | 10 | public int lengthOfLongestSubstring(String s) { 11 | if (s == null || s.length() == 0) { 12 | return 0; 13 | } 14 | 15 | // 初始化一堆遍历,默认使用第一个字符 16 | int begin = 0; 17 | int max = 1; 18 | int[] characterIndexes = new int[200]; 19 | Arrays.fill(characterIndexes, -1); 20 | characterIndexes[s.charAt(0)] = 0; 21 | 22 | for (int i = 1; i < s.length(); i++) { 23 | int index = characterIndexes[s.charAt(i)]; 24 | // 已经存在 25 | if (index >= begin) { 26 | begin = index + 1; 27 | } else { 28 | max = Math.max(max, i - begin + 1); 29 | } 30 | characterIndexes[s.charAt(i)] = i; 31 | } 32 | 33 | return max; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0004/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0004; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 5 | * 6 | * 难度在于,要求时间复杂度是 O(log(m + n)) 7 | */ 8 | public class Solution { 9 | 10 | public double findMedianSortedArrays(int[] nums1, int[] nums2) { 11 | return -1; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0009/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0009; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/palindrome-number/ 5 | * 6 | * 这个是一个比较巧妙的解法。 7 | * 8 | * 当然,也可以通过字符串来求解。 9 | */ 10 | public class Solution { 11 | 12 | public boolean isPalindrome(int x) { 13 | // 负数,天然非回文 14 | if (x < 0) { 15 | return false; 16 | } 17 | // 0 ,倜然是回文 18 | if (x == 0) { 19 | return true; 20 | } 21 | // 以 0 结尾,肯定不是回文。 22 | if (x % 10 == 0) { 23 | return false; 24 | } 25 | 26 | int y = 0; 27 | // 当原始数字 x 小于反转后的数字 y 时,就意味着我们已经处理了一半位数的数字。 28 | while (x > y) { 29 | y = y * 10 + x % 10; 30 | x = x / 10; 31 | } 32 | 33 | return y == x // 位数为偶数 34 | || x == y / 10; // 位数为奇数,y 会比 x 多一位 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0011/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0011; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/container-with-most-water/ 5 | * 6 | * 双指针 7 | * 8 | * 参考博客:https://leetcode-cn.com/problems/container-with-most-water/solution/container-with-most-water-shuang-zhi-zhen-fa-yi-do/ 9 | */ 10 | public class Solution { 11 | 12 | public int maxArea(int[] height) { 13 | int max = 0; 14 | int left = 0, right = height.length - 1; 15 | while (left < right) { 16 | if (height[left] > height[right]) { 17 | max = Math.max(height[right] * (right - left), max); 18 | right--; 19 | } else { 20 | max = Math.max(height[left] * (right - left), max); 21 | left++; 22 | } 23 | } 24 | 25 | return max; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(solution.maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7})); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0019/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0019; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.ListNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/ 7 | * 8 | * 双指针实现。 9 | * 10 | * 感兴趣的同学,可以通过递归,模拟入栈,然后出栈去移除。 11 | */ 12 | public class Solution { 13 | 14 | public ListNode removeNthFromEnd(ListNode head, int n) { 15 | // 虚拟头节点,方便处理,移除头节点的情况。 16 | ListNode dummy = new ListNode(0); 17 | dummy.next = head; 18 | 19 | // 先使用 fast 走 n + 1 步,fast 和 slow 就刚好差 n 个节点。 20 | // 这样,后续 fast 和 slow 每人走一步,最终 fast 走到结尾时,slow 就在倒数 n 位置。 21 | ListNode fast = dummy; 22 | ListNode slow = dummy; 23 | for (int i = 0; i < n; i++) { 24 | fast = fast.next; 25 | } 26 | 27 | // 因为,要删除倒数第 n 个节点,所以 slow 走到倒数第 n + 1 个节点,就要停止了。因此这里判断 fast.next = null 为结尾 28 | while (fast.next != null) { 29 | fast = fast.next; 30 | slow = slow.next; 31 | } 32 | slow.next = slow.next.next; // 删除第 n 个节点 33 | 34 | return dummy.next; 35 | } 36 | 37 | public static void main(String[] args) { 38 | Solution solution = new Solution(); 39 | solution.removeNthFromEnd(ListNode.create(1, 2, 3, 4, 5), 5); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0022/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0022; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/generate-parentheses 8 | * 9 | * 回溯算法 10 | */ 11 | public class Solution { 12 | 13 | private List results = new ArrayList<>(); 14 | 15 | public List generateParenthesis(int n) { 16 | this.backtracking(0, 0, n, ""); 17 | return results; 18 | } 19 | 20 | private void backtracking(int leftCounts, int rightCounts, int n, String current) { 21 | if (leftCounts == n && rightCounts == n) { 22 | results.add(current); 23 | return; 24 | } 25 | 26 | // 左括号 ( 27 | if (leftCounts < n) { 28 | this.backtracking(leftCounts + 1, rightCounts, n, current + "("); 29 | } 30 | // 右括号 ) 31 | if (rightCounts < leftCounts) { 32 | this.backtracking(leftCounts, rightCounts + 1, n, current + ")"); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0024/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0024; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0024/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0024; 2 | 3 | /** 4 | * 递归实现 5 | * 6 | * 相对比较简洁 7 | */ 8 | public class Solution02 { 9 | 10 | public ListNode swapPairs(ListNode head) { 11 | // 如果无,就跳过 12 | if(head == null || head.next == null){ 13 | return head; 14 | } 15 | 16 | // 交换 17 | ListNode next = head.next; // 选择下一个 18 | head.next = swapPairs(next.next); // 递归,以 head 的下两个节点为开始的子链表,进行交换。同时 head.next 指向子链表的头 19 | next.next = head; // 将 next 和 head 交换 20 | 21 | // 返回结果 22 | return next; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0024/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0024; 2 | 3 | /** 4 | * 和 {@link Solution} 一个思路,就是代码更漂亮 5 | */ 6 | @SuppressWarnings("ConstantConditions") 7 | public class Solution03 { 8 | 9 | public ListNode swapPairs(ListNode head) { 10 | // 创建一个前置的特殊节点,指向 head 。这样,就能统一,站在第 -1 个节点,看 0,1 交换。站在 1 个节点,看 2,3 交换。。相比我之前写的代码,会更加统一。 11 | ListNode pre = new ListNode(0); 12 | pre.next = head; 13 | 14 | // 设置 temp ,开始往下循环。 15 | ListNode temp = pre; 16 | while(temp.next != null && temp.next.next != null) { 17 | // 下一个节点,和下两个节点 18 | ListNode start = temp.next; 19 | ListNode end = temp.next.next; 20 | // tmp 指向下两个节点 21 | temp.next = end; 22 | // 下一个节点,指向下三个节点 23 | start.next = end.next; 24 | // 下两个节点,指向下一个节点 25 | end.next = start; 26 | // tmp 指向 start 27 | temp = start; 28 | // 小结,确实会比我写的清晰一些。很多时候,特殊的头节点,能带来这样的好处。 29 | } 30 | 31 | return pre.next; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0025/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0025; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0026/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0026; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ 5 | * 6 | * 从逻辑来说,貌似也算“双指针”,一个 i ,一个 idx 。。。 7 | */ 8 | public class Solution { 9 | 10 | public int removeDuplicates(int[] nums) { 11 | if (nums.length == 0) { 12 | return 0; 13 | } 14 | 15 | int idx = 1; // 从 1 开始,减少多余的每次的 i > 0 的判断 16 | for (int i = 1; i < nums.length; i++) { 17 | // 等于前一个元素,跳过 18 | if (nums[i] == nums[i - 1]) { 19 | continue; 20 | } 21 | nums[idx] = nums[i]; 22 | idx++; 23 | } 24 | 25 | return idx; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(solution.removeDuplicates(new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4})); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0027/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0027; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/remove-element/ 5 | */ 6 | public class Solution { 7 | 8 | public int removeElement(int[] nums, int val) { 9 | int idx = 0; 10 | for (int num : nums) { 11 | if (num == val) { 12 | continue; 13 | } 14 | nums[idx] = num; 15 | idx++; 16 | } 17 | return idx; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0027/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0027; 2 | 3 | /** 4 | * 相比 {@link Solution} 来说,优势在于,Solution02 可以减少移动的次数 5 | */ 6 | public class Solution02 { 7 | 8 | public int removeElement(int[] nums, int val) { 9 | int idx = 0; 10 | int n = nums.length; 11 | while (idx < n) { 12 | if (nums[idx] == val) { 13 | nums[idx] = nums[n - 1]; 14 | n--; // 此处,非常关键,减小的是 n ,而 idx 没有增加,那么 while 下一轮,就会判断此处的 nums[n - 1] 是否也有可能等于 val 15 | } else { 16 | idx++; 17 | } 18 | } 19 | 20 | return n; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0035/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0035; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/search-insert-position/ 5 | */ 6 | public class Solution { 7 | 8 | public int searchInsert(int[] nums, int target) { 9 | int left = 0, right = nums.length - 1; 10 | while (left <= right) { 11 | int middle = left + ((right - left) >> 1); 12 | if (nums[middle] == target) { 13 | return middle; 14 | } 15 | if (nums[middle] < target) { 16 | left = middle + 1; 17 | } else { 18 | right = middle - 1; 19 | } 20 | } 21 | 22 | // 相比来说,返回 left ,表示最接近的位置 23 | return left; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | // System.out.println(solution.searchInsert(new int[]{1, 3, 5, 6}, 5)); 29 | // System.out.println(solution.searchInsert(new int[]{1, 3, 5, 6}, 2)); 30 | // System.out.println(solution.searchInsert(new int[]{1, 3, 5, 6}, 7)); 31 | System.out.println(solution.searchInsert(new int[]{1, 3, 5, 6}, 0)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0042/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0042; 2 | 3 | /** 4 | * 暴力解,每个节点,求左右两边的最大值 5 | */ 6 | public class Solution02 { 7 | 8 | public int trap(int[] height) { 9 | int sum = 0; 10 | for (int i = 1; i < height.length - 1; i++) { 11 | // 左边最大值 12 | int leftMax = height[i]; 13 | for (int j = i - 1; j >= 0; j--) { 14 | leftMax = Math.max(leftMax, height[j]); 15 | } 16 | // 右边最大值 17 | int rightMax = height[i]; 18 | for (int j = i + 1; j < height.length; j++) { 19 | rightMax = Math.max(rightMax, height[j]); 20 | } 21 | 22 | // 增加结果 23 | sum += Math.min(leftMax, rightMax) - height[i]; 24 | } 25 | return sum; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution02 solution = new Solution02(); 30 | System.out.println(solution.trap(new int[]{0,1,0,2,1,0,1,3,2,1,2,1})); 31 | // System.out.println(solution.trap(new int[]{2, 0, 2})); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0045/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0045; 2 | 3 | /** 4 | * 贪心算法 5 | * 6 | * 不断到达边界,如果到达边界后,最大步数加一。 7 | * 8 | * 相当于说,走一步,看看这一步能走到的最大边界是哪里。 9 | * 10 | * 例如说,2,3,1,1,4,6 11 | * 12 | * 第一轮, 13 | * 初始在第 0 的位置,跳到最远是第 2 个位置,此时使用了一步,step = 1 。 14 | * 15 | * 第二轮, 16 | * 在第 1 的位置,跳到最远是第 5 个位置。 17 | * 在第 2 的位置,跳到最远是滴 3 个位置。 18 | * - 相比第 5 个位置,更近,所以此时最远的还是第 5 个位置。 19 | * - 此时,第 2 个位置,是第一轮的边界,所以 step = 2 ,最远是第 5 个位置。 20 | * 21 | * 第三轮, 22 | * 在第 3 的位置,跳到 4 个位置。相比最远的还是第 5 个位置,还是小。 23 | * 在第 4 的位置,跳到 8 个位置。已经到达终点。 24 | * - 此时,第 5 个位置是第二轮的边界,所以 step = 3 ,最远是滴 8 个位置。 25 | * 26 | * 至此,就基本结束了。😈 胖友在对着代码,瞅一瞅。其实,有点 BFS 的感觉,一轮一轮的。 27 | */ 28 | public class Solution02 { 29 | 30 | public int jump(int[] nums) { 31 | int end = 0; // 边界 32 | int maxPosition = 0; // 最大位置 33 | int step = 0; 34 | for (int i = 0; i < nums.length - 1; i++) { // 最后一个位置,不用再往下 35 | // 找到最远可以跳到的位置 36 | maxPosition = Math.max(maxPosition, i + nums[i]); 37 | // 判断是否走到边界 38 | if (i == end) { 39 | end = maxPosition; 40 | step++; 41 | } 42 | } 43 | return step; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0045/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0045; 2 | 3 | /** 4 | * 数组 5 | * 6 | * 先站在终点 position = nums.length - 1; 7 | * 8 | * 不断从 [0, position) 的位置,走到 position 。 9 | */ 10 | public class Solution03 { 11 | 12 | public int jump(int[] nums) { 13 | int position = nums.length - 1; 14 | int step = 0; 15 | while (position > 0) { // 未到达终点 16 | // 从左到右,判断是否能到达 position 的最早位置。 17 | for (int i = 0; i < position; i++) { 18 | if (i + nums[i] >= position) { 19 | step++; 20 | position = i; 21 | break; 22 | } 23 | } 24 | } 25 | return step; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0049/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0049; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/group-anagrams/ 7 | * 8 | * 使用排序实现 9 | */ 10 | public class Solution { 11 | 12 | public List> groupAnagrams(String[] strs) { 13 | Map> group = new HashMap<>(); 14 | 15 | for (String str : strs) { 16 | // 获得 key 17 | String key = this.getKey(str); 18 | 19 | // 添加到 group 中 20 | List values = group.computeIfAbsent(key, k -> new ArrayList<>()); 21 | values.add(str); 22 | } 23 | 24 | return new ArrayList<>(group.values()); 25 | } 26 | 27 | private String getKey(String str) { 28 | char[] keyCharArray = str.toCharArray(); 29 | Arrays.sort(keyCharArray); 30 | return new String(keyCharArray); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0049/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0049; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 考虑到字符都是小写,所以通过计数排序 7 | */ 8 | public class Solution02 { 9 | 10 | public List> groupAnagrams(String[] strs) { 11 | Map> group = new HashMap<>(); 12 | 13 | for (String str : strs) { 14 | // 获得 key 15 | String key = this.getKey(str); 16 | 17 | // 添加到 group 中 18 | List values = group.computeIfAbsent(key, k -> new ArrayList<>()); 19 | values.add(str); 20 | } 21 | 22 | return new ArrayList<>(group.values()); 23 | } 24 | 25 | private String getKey(String str) { 26 | int[] counts = new int[26]; 27 | for (char ch : str.toCharArray()) { 28 | counts[ch - 'a']++; 29 | } 30 | StringBuilder sb = new StringBuilder(26 * 2); 31 | for (int count : counts) { 32 | sb.append(count).append("#"); 33 | } 34 | return sb.toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0049/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0049; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 考虑到字符都是小写,所以通过计数排序 7 | */ 8 | public class Solution03 { 9 | 10 | public List> groupAnagrams(String[] strs) { 11 | Map> group = new HashMap<>(); 12 | 13 | for (String str : strs) { 14 | // 获得 key 15 | int key = this.getKey(str); 16 | 17 | // 添加到 group 中 18 | List values = group.computeIfAbsent(key, k -> new ArrayList<>()); 19 | values.add(str); 20 | } 21 | 22 | return new ArrayList<>(group.values()); 23 | } 24 | 25 | // 极端情况下,可能会哈希碰撞。当然,这里能够 AC ,估计是测试集太小,也没必要。 26 | private int getKey(String str) { 27 | int[] counts = new int[26]; 28 | for (char ch : str.toCharArray()) { 29 | counts[ch - 'a']++; 30 | } 31 | return Arrays.hashCode(counts); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0053/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0053; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/maximum-subarray/ 5 | * 6 | * 贪心算法 7 | * 8 | * 不断计算使用当前值的最大值,然后和全局最大值比较。 9 | */ 10 | public class Solution { 11 | 12 | public int maxSubArray(int[] nums) { 13 | if (nums.length == 0) { 14 | return 0; 15 | } 16 | int result = nums[0]; // 全局最大值 17 | int max = nums[0]; // 使用当前数字,能产生的最大值 18 | for (int i = 1; i < nums.length; i++) { 19 | // 计算使用当前值的最大值 20 | max = Math.max(max + nums[i], nums[i]); 21 | // 计算全局最大值 22 | result = Math.max(result, max); 23 | } 24 | return result; 25 | } 26 | 27 | public static void main(String[] args) { 28 | Solution solution = new Solution(); 29 | System.out.println(solution.maxSubArray(new int[]{-2,1,-3,4,-1,2,1,-5,4})); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0053/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0053; 2 | 3 | /** 4 | * TODO 分治算法 5 | * TODO 动态规划 6 | * 7 | * https://leetcode-cn.com/problems/maximum-subarray/solution/bao-li-qiu-jie-by-pandawakaka/ 8 | */ 9 | public class SolutionX { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0055/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0055; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/jump-game/ 5 | * 6 | * 数组 7 | * 8 | * 顺着从头晚跳,记录最远可跳位置。只要当前位置小于最远位置,说明可以达到。 9 | */ 10 | public class Solution { 11 | 12 | public boolean canJump(int[] nums) { 13 | int max = 0; 14 | for (int i = 0; i < nums.length; i++) { 15 | // 判断是否不可达 16 | if (i > max) { 17 | return false; 18 | } 19 | // 计算新的 max 20 | max = Math.max(max, i + nums[i]); 21 | } 22 | return true; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Solution solution = new Solution(); 27 | System.out.println(solution.canJump(new int[]{2,3,1,1,4})); 28 | System.out.println(solution.canJump(new int[]{3,2,1,0,4})); 29 | System.out.println(solution.canJump(new int[]{0})); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0055/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0055; 2 | 3 | /** 4 | * 贪心算法 5 | * 6 | * 相比 {@link Solution} 来说,每一次循环,少一次计算,所以更快一些。所以,速度上会更快一些 7 | */ 8 | public class Solution02 { 9 | 10 | public boolean canJump(int[] nums) { 11 | int minPosition = nums.length - 1; 12 | for (int i = minPosition; i >= 0; i--) { 13 | if (nums[i] + i >= minPosition) { 14 | minPosition = i; 15 | } 16 | } 17 | return minPosition == 0; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0055/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0055; 2 | 3 | /** 4 | * 动态规划 5 | * 6 | * 自顶向上,判断当前节点开始 + 1 到 nums[i] 个节点,是否可以访问到。 7 | */ 8 | public class Solution03 { 9 | 10 | public boolean canJump(int[] nums) { 11 | // 创建状态数组,记录该节点是否可以访问。 12 | boolean[] dps = new boolean[nums.length]; 13 | dps[nums.length - 1] = true; // 最后一个节点可访问 14 | 15 | // 倒序遍历 16 | for (int i = nums.length - 2; i >= 0; i--) { 17 | dps[i] = this.canVisit(dps, 18 | i + 1, 19 | Math.min(i + nums[i], nums.length - 1)); // 结尾 20 | } 21 | return dps[0]; 22 | } 23 | 24 | private boolean canVisit(boolean[] dps, int start, int end) { 25 | for (int i = start; i <= end; i++) { 26 | if (dps[i]) { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0062/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0062; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/unique-paths/ 5 | * 6 | * 动态规划 7 | * 8 | * 路径数,dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 9 | * 10 | * 考虑到只能向右或者向下走,所以可以进一步数组压缩,从二维,变成一唯。 11 | */ 12 | public class Solution { 13 | 14 | public int uniquePaths(int m, int n) { 15 | if (m == 0 || n == 0) { 16 | return 0; 17 | } 18 | 19 | // 创建数组,设置默认肯定有 1 条路径 20 | int[] dp = new int[n + 1]; 21 | dp[0] = 1; 22 | 23 | for (int i = 0; i < m; i++) { 24 | for (int j = 1; j < n; j++) { // 第一列,只会一直向下 25 | dp[j] = dp[j - 1] + dp[j]; 26 | } 27 | } 28 | return dp[n - 1]; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution solution = new Solution(); 33 | // System.out.println(solution.uniquePaths(3, 2)); 34 | // System.out.println(solution.uniquePaths(7, 3)); 35 | System.out.println(solution.uniquePaths(3, 3)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0064/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0064; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/minimum-path-sum/ 5 | * 6 | * 动态规划 7 | * 8 | * dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + dp[i][j] 9 | * 10 | * 因为不会重复遍历,所以直接使用 grid 存储结果. 11 | */ 12 | public class Solution { 13 | 14 | public int minPathSum(int[][] grid) { 15 | int n = grid.length; 16 | if (n == 0) { 17 | return 0; 18 | } 19 | int m = grid[0].length; 20 | 21 | // 逐行,计算结果 22 | for (int i = 0; i < n; i++) { 23 | for (int j = 0; j < m; j++) { 24 | if (i == 0 && j == 0) { 25 | continue; 26 | } 27 | int above = i > 0 ? grid[i - 1][j] : Integer.MAX_VALUE; 28 | int left = j > 0 ? grid[i][j - 1] : Integer.MAX_VALUE; 29 | grid[i][j] = Math.min(above, left) + grid[i][j]; 30 | } 31 | } 32 | return grid[n - 1][m - 1]; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0070/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0070; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/climbing-stairs/ 5 | * 6 | * 动态规划 7 | * 8 | * 表达式是,f(n) = f(n - 1) + f(n - 2) 9 | */ 10 | public class Solution { 11 | 12 | public int climbStairs(int n) { 13 | if (n <= 1) { 14 | return n; 15 | } 16 | int f0 = 1; 17 | int f1 = 1; 18 | for (int i = 2; i <= n; i++) { 19 | // 计算 f0 和 f1 到下一个 f2 的方案 20 | int f2 = f0 + f1; 21 | // 设置 f0、f1 22 | f0 = f1; 23 | f1 = f2; 24 | } 25 | return f1; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(solution.climbStairs(2)); 31 | // System.out.println(solution.climbStairs(3)); 32 | // System.out.println(solution.climbStairs(4)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0070/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0070; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode/ 5 | * 6 | * TODO 方法五 Binets 方法 7 | * TODO 方法六 斐波那契公式 8 | */ 9 | public class SolutionX { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0074/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0074; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/search-a-2d-matrix/ 5 | * 6 | * 暴力求解 7 | */ 8 | public class Solution { 9 | 10 | public boolean searchMatrix(int[][] matrix, int target) { 11 | if (matrix.length == 0) { 12 | return false; 13 | } 14 | for (int[] ints : matrix) { 15 | for (int j = 0; j < matrix[0].length; j++) { 16 | if (ints[j] == target) { 17 | return true; 18 | } 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0074/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0074; 2 | 3 | /** 4 | * 二分查找 5 | */ 6 | public class Solution02 { 7 | 8 | public boolean searchMatrix(int[][] matrix, int target) { 9 | if (matrix.length == 0) { 10 | return false; 11 | } 12 | int row = matrix.length, col = matrix[0].length; 13 | 14 | // 二分查找 15 | int left = 0, right = row * col - 1; 16 | while (left <= right) { 17 | int mid = left + ((right - left) >> 1); 18 | int value = matrix[mid / col][mid % col]; 19 | if (value == target) { 20 | return true; 21 | } 22 | if (value > target) { 23 | right = mid - 1; 24 | } else { 25 | left = mid + 1; 26 | } 27 | } 28 | 29 | return false; 30 | } 31 | 32 | public static void main(String[] args) { 33 | Solution02 solution = new Solution02(); 34 | System.out.println(solution.searchMatrix(new int[][]{ 35 | {1, 3, 5, 7}, 36 | {10, 11, 16, 20}, 37 | {23, 30, 34, 50} 38 | }, 3)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0075/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0075; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/sort-colors/ 5 | * 6 | * 双指针 7 | */ 8 | public class Solution { 9 | 10 | public void sortColors(int[] nums) { 11 | int zero = -1; // 指向最后一个 0 12 | int two = nums.length; // 指向最后一个 2 13 | int one = 0; 14 | 15 | while(one < two) { 16 | int num = nums[one]; 17 | if (num == 0) { // 指向 0 的情况 18 | swap(nums, zero + 1, one); 19 | zero++; // 指向最后一个 0 20 | one++; // 跳到下一个 21 | } else if (num == 2) { 22 | swap(nums, two - 1, one); 23 | two--; // 指向最后一个 2 24 | // 注意,此处不会将 one++ ,因为要考虑,交换过来的数字的情况,到底是 0,还是 1 。 25 | } else { 26 | one++; 27 | } 28 | } 29 | } 30 | 31 | private void swap(int[] nums, int i, int j) { 32 | int tmp = nums[i]; 33 | nums[i] = nums[j]; 34 | nums[j] = tmp; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0077/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0077; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/combinations/ 9 | * 10 | * 回溯算法 11 | */ 12 | public class Solution { 13 | 14 | private List> result = new ArrayList<>(); 15 | 16 | public List> combine(int n, int k) { 17 | if (n == 0 || k == 0 || k > n) { 18 | return Collections.emptyList(); 19 | } 20 | this.backtracking(n, k, 1, new ArrayList<>()); 21 | return result; 22 | } 23 | 24 | private void backtracking(int n, int k, int start, List current) { 25 | if (k == 0) { 26 | result.add(new ArrayList<>(current)); 27 | return; 28 | } 29 | for (int i = start; i <= n - k + 1; i++) { 30 | // 添加到结果 31 | current.add(i); 32 | // 递归 33 | this.backtracking(n, k - 1, i + 1, current); 34 | // 移除出结果 35 | current.remove(current.size() - 1); 36 | } 37 | } 38 | 39 | public static void main(String[] args) { 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0077/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0077; 2 | 3 | /** 4 | * TODO 芋艿 5 | * 6 | * 还有各种神奇的解法,看 https://leetcode-cn.com/problems/combinations/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-1-9/ 博客 7 | * 8 | * 以及 https://leetcode-cn.com/problems/combinations/solution/zu-he-by-leetcode/ 方法二 9 | */ 10 | public class SolutionX { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0078/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0078; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/subsets/ 8 | * 9 | * 回溯算法 10 | */ 11 | public class Solution { 12 | 13 | private List> results = new ArrayList<>(); 14 | 15 | public List> subsets(int[] nums) { 16 | this.backtracking(nums, 0, new ArrayList<>()); 17 | return results; 18 | } 19 | 20 | private void backtracking(int[] nums, int index, List current) { 21 | // 添加到结果 22 | results.add(new ArrayList<>(current)); 23 | 24 | // 回溯 25 | for (int i = index; i < nums.length; i++) { 26 | current.add(nums[i]); 27 | this.backtracking(nums, i + 1, current); 28 | current.remove(current.size() - 1); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0080/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0080; 2 | 3 | /** 4 | * 通用模板,可以将 k 变量,修改成任意一个有序数组中,允许的一个数字的数量 5 | * 6 | * 参考博客:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/solution/shan-chu-pai-xu-shu-zu-zhong-de-zhong-fu-xiang-i-2/ 7 | */ 8 | public class Solution02 { 9 | 10 | public int removeDuplicates(int[] nums) { 11 | int k = 2; 12 | if (nums.length <= k) { 13 | return nums.length; 14 | } 15 | 16 | int idx = k; 17 | for (int i = k; i < nums.length; i++) { 18 | // 位置 i ,直接和位置 idx - k 比较,而跳过了位置 idx - k + 1 ... 的元素。 19 | // 因为有序,只要 nums[i] == nums[idx - k] 成立,意味着 nums[i] == nums[idx - k + 1] 也成立。 20 | if (nums[i] == nums[idx - k]) { 21 | continue; 22 | } 23 | // 设置 24 | nums[idx] = nums[i]; 25 | idx++; 26 | } 27 | 28 | return idx; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution02 solution = new Solution02(); 33 | System.out.println(solution.removeDuplicates(new int[]{1, 1, 1, 2, 2, 3})); 34 | System.out.println(solution.removeDuplicates(new int[]{0, 0, 1, 1, 1, 1, 2, 3, 3})); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0082/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0082; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.ListNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/ 7 | */ 8 | public class Solution { 9 | 10 | public ListNode deleteDuplicates(ListNode head) { 11 | if (head == null || head.next == null) { 12 | return head; 13 | } 14 | 15 | ListNode dummy = new ListNode(0); 16 | dummy.next = head; 17 | 18 | ListNode prev = dummy; // 注意,此时,是站在 dummy 开始 19 | while (prev.next != null) { 20 | ListNode lastDuplicate = findDuplicateNode(prev.next); 21 | // 如果就是自己,说明没有相等的,直接下跳。 22 | if (prev.next == lastDuplicate) { 23 | prev = prev.next; 24 | // 如果不是自己,说明有重复的,跳到最后重复的下一个。 25 | } else { 26 | prev.next = lastDuplicate.next; 27 | } 28 | } 29 | 30 | return dummy.next; 31 | } 32 | 33 | private ListNode findDuplicateNode(ListNode node) { 34 | int val = node.val; 35 | while (node.next != null && node.next.val == val) { 36 | node = node.next; 37 | } 38 | return node; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0084/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0084; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ 5 | * 6 | * 每个节点,如果左(右)节点比自己打,则进行遍历。 7 | * 如此,我们就能求出,以当前节点为高度,最大能到达多远,从而计算出宽度 = right - left + 1 。 8 | * 然后求面积,求最大值。 9 | */ 10 | public class Solution { 11 | 12 | public int largestRectangleArea(int[] heights) { 13 | int max = 0; 14 | for (int i = 0; i < heights.length; i++) { 15 | // left 下标 16 | int left = i; 17 | while (left > 0 && heights[left - 1] >= heights[i]) { 18 | left--; 19 | } 20 | // right 下标 21 | int right = i; 22 | while (right < heights.length - 1 && heights[right + 1] >= heights[i]) { 23 | right++; 24 | } 25 | // 求 max 26 | max = Math.max(max, (right - left + 1) * heights[i]); 27 | } 28 | return max; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution solution = new Solution(); 33 | System.out.println(solution.largestRectangleArea(new int[]{2, 1, 5, 6, 2, 3})); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0084/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0084; 2 | 3 | /** 4 | * 分治算法 5 | * 6 | * 将求整个区间内的最大面积,分治成多个区间的最大面积。 7 | * 8 | * 平均时间复杂度,O(nlogn) 9 | * 最差时间复杂度,O(n^2) 10 | * 11 | * 有个方案优化,稳定在 O(nlogn) ,具体是 https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/zhu-zhuang-tu-zhong-zui-da-de-ju-xing-by-leetcode/ 方法四。 12 | */ 13 | public class Solution03 { 14 | 15 | private int partition(int[] heights, int start, int end) { 16 | if (start > end) { 17 | return 0; 18 | } 19 | int minIndex = start; 20 | for (int i = start + 1; i <= end; i++) { 21 | if (heights[i] < heights[minIndex]) { 22 | minIndex = i; 23 | } 24 | } 25 | // 当前面积 26 | int area = heights[minIndex] * (end - start + 1); 27 | // 左右面积 28 | int left = this.partition(heights, start, minIndex - 1); 29 | int right = this.partition(heights, minIndex + 1, end); 30 | return Math.max(area, Math.max(left, right)); 31 | } 32 | 33 | public int largestRectangleArea(int[] heights) { 34 | return this.partition(heights, 0, heights.length - 1); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0088/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0088; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/merge-sorted-array/ 5 | * 6 | * 因为 nums1 的大小,是 m + n ,所以空间是足够的 7 | * 又因为,从头开始比较会导致覆盖,所以从尾部开始比较。 8 | * 9 | * 当然,该方法,还有其他解决方案,都不如这个,嘿嘿。可以查看:https://leetcode-cn.com/problems/merge-sorted-array/solution/he-bing-liang-ge-you-xu-shu-zu-by-leetcode/ 10 | */ 11 | public class Solution { 12 | 13 | public void merge(int[] nums1, int m, int[] nums2, int n) { 14 | // 开始比较 15 | int idx = nums1.length - 1; 16 | while (n > 0 && m > 0) { 17 | if (nums1[m - 1] > nums2[n - 1]) { 18 | nums1[idx] = nums1[m - 1]; 19 | idx--; 20 | m--; 21 | } else { 22 | nums1[idx] = nums2[n - 1]; 23 | idx--; 24 | n--; 25 | } 26 | } 27 | 28 | // 如果 nums2 还有剩余,复制到 nums1 中 29 | if (n > 0) { 30 | System.arraycopy(nums2, 0, nums1, 0, n); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0090/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0090; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/subsets-ii/ 9 | * 10 | * 回溯算法 11 | */ 12 | public class Solution { 13 | 14 | private List> results = new ArrayList<>(); 15 | 16 | public List> subsetsWithDup(int[] nums) { 17 | Arrays.sort(nums); 18 | this.backtracking(nums, 0, new ArrayList<>()); 19 | return results; 20 | } 21 | 22 | private void backtracking(int[] nums, int index, List current) { 23 | // 添加到结果 24 | results.add(new ArrayList<>(current)); 25 | 26 | // 回溯 27 | Integer last = null; 28 | for (int i = index; i < nums.length; i++) { 29 | if (last != null && last == nums[i]) { 30 | continue; 31 | } 32 | last = nums[i]; 33 | // 继续回溯 34 | current.add(nums[i]); 35 | this.backtracking(nums, i + 1, current); 36 | current.remove(current.size() - 1); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0092/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0092; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0094/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0094; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/binary-tree-inorder-traversal/ 10 | * 11 | * 递归 12 | */ 13 | public class Solution { 14 | 15 | private List results = new ArrayList<>(); 16 | 17 | public List inorderTraversal(TreeNode root) { 18 | this.recursion(root); 19 | 20 | return results; 21 | } 22 | 23 | public void recursion(TreeNode node) { 24 | if (node == null) { 25 | return; 26 | } 27 | 28 | // 左节点 29 | this.recursion(node.left); 30 | 31 | // 当前节点 32 | this.visit(node); 33 | 34 | // 右节点 35 | this.recursion(node.right); 36 | } 37 | 38 | private void visit(TreeNode node) { 39 | this.results.add(node.val); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0094/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0094; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Stack; 8 | 9 | /** 10 | * 迭代 11 | */ 12 | public class Solution02 { 13 | 14 | public List inorderTraversal(TreeNode root) { 15 | List results = new ArrayList<>(); 16 | 17 | Stack stack = new Stack<>(); 18 | TreeNode current = root; 19 | while (current != null || !stack.isEmpty()) { 20 | // 获得当前节点的左节点 21 | while (current != null) { 22 | stack.push(current); 23 | current = current.left; 24 | } 25 | // 获得新的当前节点 26 | current = stack.pop(); 27 | results.add(current.val); 28 | // 获得右节点 29 | current = current.right; 30 | } 31 | 32 | return results; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0094/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0094; 2 | 3 | /** 4 | * TODO 莫里斯遍历 5 | * 6 | * 可参考 https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode/ 的方法三 7 | */ 8 | public class Solution03 { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0095/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0095; 2 | 3 | /** 4 | * TODO 后续理解,想能更好。 5 | * 6 | * 参考博客 https://leetcode-cn.com/problems/unique-binary-search-trees-ii/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-2-7/ 7 | * 方法三或者方法四 8 | * 9 | * 动态规划 10 | */ 11 | public class Solution02 { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0096/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0096; 2 | 3 | /** 4 | * 动态规划 5 | */ 6 | public class Solution02 { 7 | 8 | public int numTrees(int n) { 9 | // 创建数组,记录 n 节可创建的二叉搜索树 10 | int[] numTrees = new int[n + 1]; 11 | numTrees[0] = numTrees[1] = 1; 12 | // 计算 i 个节点,可创建的二叉搜索树的数量 13 | // 以 i 为例子,则二叉搜索树,可以拆分成 [j, 1, i - j - 1] 三部分 14 | // 并且有一点要注意,1,2,3 和 4,5,6 两种 3 节点,实际创建的二叉树数量,是一致的。 15 | for (int i = 2; i <= n; i++) { 16 | for (int j = 0; j < i; j++) { 17 | numTrees[i] += numTrees[j] * numTrees[i - j - 1]; 18 | } 19 | } 20 | 21 | // 返回结果 22 | return numTrees[n]; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0096/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0096; 2 | 3 | /** 4 | * 参考 https://leetcode-cn.com/problems/unique-binary-search-trees/solution/bu-tong-de-er-cha-sou-suo-shu-by-leetcode/ 5 | * 6 | * 方法二,数学演绎法。这个就太 666 了,知道就好。 7 | */ 8 | public class Solution03 { 9 | 10 | public int numTrees(int n) { 11 | long c = 1; 12 | // 遍历, 13 | for (int i = 0; i < n; i++) { 14 | c = c * 2 * (2 * i + 1) / (i + 2); 15 | } 16 | 17 | // 返回结果 18 | return (int) c; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0098/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0098; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/validate-binary-search-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public boolean isValidBST(TreeNode root) { 11 | return this.isValidBST(root, null, null); 12 | } 13 | 14 | private boolean isValidBST(TreeNode node, Integer min, Integer max) { 15 | // 空的情况 16 | if (node == null) { 17 | return true; 18 | } 19 | 20 | // 判断节点是否有效 21 | if (min != null && min >= node.val) { 22 | return false; 23 | } 24 | if (max != null && max <= node.val) { 25 | return false; 26 | } 27 | 28 | // 左子树,最大值不能到达 node.val 29 | return this.isValidBST(node.left, min, node.val) 30 | // 右子树,最小值必须超过 node.val 31 | && this.isValidBST(node.right, node.val, max); 32 | } 33 | 34 | public static void main(String[] args) { 35 | Solution solution = new Solution(); 36 | TreeNode node = TreeNode.create(10,5,15,null,null,6,20); 37 | System.out.println(solution.isValidBST(node)); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0100/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0100; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/same-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public boolean isSameTree(TreeNode p, TreeNode q) { 11 | if (p == null && q == null) { 12 | return true; 13 | } else if (p == null || q == null) { 14 | return false; 15 | } else if (p.val != q.val) { 16 | return false; 17 | } 18 | 19 | return this.isSameTree(p.left, q.left) 20 | && this.isSameTree(p.right, q.right); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0101/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0101; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/symmetric-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public boolean isSymmetric(TreeNode root) { 11 | if (root == null) { 12 | return true; 13 | } 14 | 15 | return this.isMirror(root.left, root.right); 16 | } 17 | 18 | private boolean isMirror(TreeNode left, TreeNode right) { 19 | if (left == null && right == null) { 20 | return true; 21 | } 22 | if (left == null || right == null) { 23 | return false; 24 | } 25 | if (left.val != right.val) { 26 | return false; 27 | } 28 | 29 | return isMirror(left.right, right.left) 30 | && isMirror(left.left, right.right); 31 | } 32 | 33 | public static void main(String[] args) { 34 | Solution solution = new Solution(); 35 | TreeNode node = TreeNode.create(1, 2, 2, 3, 4, 4, 3); 36 | System.out.println(solution.isSymmetric(node)); 37 | node = TreeNode.create(1, 2, 2, null, 3, null, 3); 38 | System.out.println(solution.isSymmetric(node)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0104/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0104; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public int maxDepth(TreeNode root) { 11 | return dfs(root, 0); 12 | } 13 | 14 | public int dfs(TreeNode node, int depth) { 15 | if (node == null) { 16 | return depth; 17 | } 18 | 19 | int leftDepth = dfs(node.left, depth + 1); 20 | int rightDepth = dfs(node.right, depth + 1); 21 | return Math.max(leftDepth, rightDepth); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0108/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0108; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/ 7 | * 8 | * 递归 9 | */ 10 | public class Solution { 11 | 12 | public TreeNode sortedArrayToBST(int[] nums) { 13 | if (nums.length == 0) { 14 | return null; 15 | } 16 | 17 | return this.sortedArrayToBST(nums, 0, nums.length - 1); 18 | } 19 | 20 | private TreeNode sortedArrayToBST(int[] nums, int low, int high) { 21 | if (low > high) { 22 | return null; 23 | } 24 | 25 | // 因为左右高度不能超过 1 ,所以取中间 26 | int mid = low + ((high - low) >> 1); 27 | TreeNode node = new TreeNode(nums[mid]); 28 | 29 | // 左右节点 30 | node.left = this.sortedArrayToBST(nums, low, mid - 1); 31 | node.right = this.sortedArrayToBST(nums, mid + 1, high); 32 | 33 | // 返回节点 34 | return node; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0110/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0110; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/balanced-binary-tree/ 7 | */ 8 | public class Solution { 9 | 10 | /** 11 | * 是否平衡 12 | */ 13 | private boolean balanced = true; 14 | 15 | public boolean isBalanced(TreeNode root) { 16 | isBalanced(root, 0); 17 | 18 | return this.balanced; 19 | } 20 | 21 | private int isBalanced(TreeNode node, int depth) { 22 | if (node == null) { 23 | return depth; 24 | } 25 | 26 | int leftDepth = isBalanced(node.left, depth + 1); 27 | if (balanced) { // 提前结束。其实,用处不大。 28 | return -1; 29 | } 30 | 31 | int rightDepth = isBalanced(node.right, depth + 1); 32 | if (balanced) { // 提前结束。其实,用处不大。 33 | return -1; 34 | } 35 | 36 | // 判断是否不平衡 37 | if (Math.abs(leftDepth - rightDepth) > 1) { 38 | balanced = false; 39 | return -1; // 提前结束 40 | } 41 | return Math.max(leftDepth, rightDepth); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0111/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0111; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ 7 | * 8 | * 递归 9 | */ 10 | public class Solution { 11 | 12 | public int minDepth(TreeNode root) { 13 | if (root == null) { 14 | return 0; 15 | } 16 | 17 | return this.minDepth(root, 0); 18 | } 19 | 20 | private int minDepth(TreeNode node, int level) { 21 | if (node.left == null && node.right == null) { 22 | return level + 1; 23 | } 24 | 25 | int leftDepth = node.left != null ? this.minDepth(node.left, level + 1) 26 | : Integer.MAX_VALUE; 27 | int rightDepth = node.right != null ? this.minDepth(node.right, level + 1) 28 | : Integer.MAX_VALUE; 29 | return Math.min(leftDepth, rightDepth); 30 | } 31 | 32 | public static void main(String[] args) { 33 | Solution solution = new Solution(); 34 | TreeNode node = TreeNode.create(1, 2); 35 | System.out.println(solution.minDepth(node)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0111/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0111; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | /** 9 | * 队列 10 | */ 11 | public class Solution02 { 12 | 13 | public int minDepth(TreeNode root) { 14 | if (root == null) { 15 | return 0; 16 | } 17 | 18 | Queue queue = new LinkedList<>(); 19 | queue.add(root); 20 | root.val = 1; // 比较粗暴,直接把 val 改成所属层级。 21 | while (!queue.isEmpty()) { 22 | TreeNode node = queue.poll(); 23 | if (node.left == null && node.right == null) { 24 | return node.val; 25 | } 26 | if (node.left != null) { 27 | queue.add(node.left); 28 | node.left.val = node.val + 1; 29 | } 30 | if (node.right != null) { 31 | queue.add(node.right); 32 | node.right.val = node.val + 1; 33 | } 34 | } 35 | 36 | return -1; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0113/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0113; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * 在 {@link Solution} 的基础上,将字符串改成数组。 9 | */ 10 | public class Solution02 { 11 | 12 | private List> paths = new ArrayList<>(); 13 | 14 | public List> pathSum(TreeNode root, int sum) { 15 | if (root != null) { 16 | this.pathSum(root, new LinkedList<>(), sum); 17 | } 18 | 19 | return paths; 20 | } 21 | 22 | private void pathSum(TreeNode node, List path, int sum) { 23 | if (node == null) { 24 | return; 25 | } 26 | 27 | sum -= node.val; 28 | 29 | // 符合条件,添加到结果 30 | if (sum == 0 && node.left == null && node.right == null) { 31 | path = new LinkedList<>(path); 32 | path.add(node.val); 33 | paths.add(path); 34 | return; 35 | } 36 | 37 | // 添加 path 中 38 | path.add(node.val); 39 | 40 | this.pathSum(node.left, path, sum); 41 | this.pathSum(node.right, path, sum); 42 | 43 | // 移除出 path 中 44 | path.remove(path.size() - 1); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0119/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0119; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/pascals-triangle-ii/ 8 | * 9 | * 数组 10 | */ 11 | public class Solution { 12 | 13 | public List getRow(int rowIndex) { 14 | List results = new ArrayList<>(); 15 | for (int i = 0; i <= rowIndex; i++) { 16 | results.add(1); 17 | } 18 | for (int i = 1; i < rowIndex; i++) { 19 | for (int j = i; j >= 0; j--) { 20 | int left = j - 1 >= 0 ? results.get(j - 1) : 0; 21 | int right = results.get(j); 22 | results.set(j, left + right); 23 | } 24 | } 25 | return results; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(solution.getRow(1)); 31 | System.out.println(solution.getRow(2)); 32 | System.out.println(solution.getRow(3)); 33 | System.out.println(solution.getRow(4)); 34 | System.out.println(solution.getRow(5)); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0121/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0121; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/ 5 | * 6 | * 贪心算法 7 | * 8 | * 顺序计算,利润的最大值 9 | */ 10 | public class Solution { 11 | 12 | public int maxProfit(int[] prices) { 13 | if (prices.length <= 1) { 14 | return 0; 15 | } 16 | int max = 0; // 差价最大值 17 | int buy = prices[0]; // 计算到当前,购买的最小值 18 | for (int i = 1; i < prices.length; i++) { 19 | max = Math.max(max, prices[i] - buy); 20 | buy = Math.min(buy, prices[i]); 21 | } 22 | return max; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0122/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0122; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/ 5 | * 6 | * 贪心算法 7 | * 8 | * 只有第二天有的赚,就买卖 9 | */ 10 | public class Solution { 11 | 12 | public int maxProfit(int[] prices) { 13 | int sum = 0; 14 | for (int i = 1; i < prices.length; i++) { 15 | int diffPrice = prices[i] - prices[i - 1]; 16 | if (diffPrice > 0) { 17 | sum += diffPrice; 18 | } 19 | } 20 | return sum; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0122/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0122; 2 | 3 | /** 4 | * DP 算法实现 5 | */ 6 | public class Solution02 { 7 | 8 | public int maxProfit(int[] prices) { 9 | if (prices == null || prices.length == 0) { 10 | return 0; 11 | } 12 | 13 | int zero = 0; // 无持有 14 | int one = -prices[0]; // 持有股票 15 | 16 | // 遍历,进行买卖 17 | for (int i = 1; i < prices.length; i++) { 18 | // 尝试卖出 19 | // if (one + (prices[i]) > zero) { 20 | // zero = one + prices[i]; 21 | // } 22 | zero = Math.max(zero, one + prices[i]); // 简化 23 | // 尝试买入 24 | // if (zero - prices[i] > one) { 25 | // one = zero - prices[i]; 26 | // } 27 | one = Math.max(one, zero - prices[i]); // 简化 28 | } 29 | 30 | return Math.max(one, zero); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0123/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0123; 2 | 3 | /** 4 | * 和 {@link Solution} 表达式差不多,差别在于用二维码数组,通过第二个维度,表示持有股票数量。 5 | * 6 | * 相对来说,拓展性会更好。例如说,以后可以允许同时持有多股。 7 | */ 8 | public class Solution02 { 9 | 10 | public int maxProfit(int[] prices) { 11 | if (prices == null || prices.length == 0) { 12 | return 0; 13 | } 14 | int k = 2; // 最大交易次数,只能两次 15 | // 第一维度 k ,表示当前【买入股票】的次数; 16 | // 第二维度 2 ,表示 0 - 未持有,1 - 持有 1 股 17 | // 值为最大利润 18 | int[][] dp = new int[k + 1][2]; 19 | // 初始化第一个股票的处理 20 | dp[1][1] = -prices[0]; // 买入 21 | dp[0][1] = Integer.MIN_VALUE; // 相当于赋值为空,避免直接认为持有一股时,利润为 0 。 22 | dp[2][1] = -prices[0]; // 买入 + 卖出 + 买入 23 | 24 | // 遍历,进行买卖 25 | for (int i = 1; i < prices.length; i++) { 26 | for (int j = 0; j <= k; j++) { 27 | // 尝试卖出 28 | dp[j][0] = Math.max(dp[j][0], dp[j][1] + prices[i]); 29 | // 尝试买入 30 | if (j > 0) { 31 | dp[j][1] = Math.max(dp[j][1], dp[j - 1][0] - prices[i]); 32 | } 33 | } 34 | } 35 | 36 | return Math.max(dp[1][0], dp[2][0]); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0124/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0124; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/ 7 | */ 8 | public class Solution { 9 | 10 | private int max = Integer.MIN_VALUE; 11 | 12 | public int maxPathSum(TreeNode root) { 13 | this.sum(root); 14 | 15 | return max; 16 | } 17 | 18 | public int sum(TreeNode node) { 19 | if (node == null) { 20 | return 0; 21 | } 22 | 23 | // 左右节点的最大值 24 | int leftMax = Math.max(this.sum(node.left), 0); 25 | int rightMax = Math.max(this.sum(node.right), 0); 26 | 27 | // 计算当前节点 + 左右子树的最大值 28 | int sum = node.val + leftMax + rightMax; 29 | this.max = Math.max(max, sum); 30 | 31 | // 返回带上该节点的左或右节点最大值 32 | return node.val + Math.max(leftMax, rightMax); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0126/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0126; 2 | 3 | /** 4 | * 双向 BFS 5 | * 6 | * TODO 未来在写 7 | * 8 | * 可参考博客:https://zxi.mytechroad.com/blog/searching/leetcode-126-word-ladder-ii/ 9 | */ 10 | public class Solution03 { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0128/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0128; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/longest-consecutive-sequence/ 9 | */ 10 | public class Solution { 11 | 12 | public int longestConsecutive(int[] nums) { 13 | // 创建成集合 14 | Set set = new HashSet<>(); 15 | Arrays.stream(nums).forEach(set::add); 16 | 17 | int max = 0; 18 | for (int num : nums) { 19 | int count = 1; 20 | while (set.contains(num + 1)) { 21 | num++; 22 | count++; 23 | } 24 | max = Math.max(max, count); 25 | } 26 | 27 | return max; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0128/Solution011.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0128; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * 在 {@link Solution} 的基础上,进一步优化,减少重复计算 8 | */ 9 | public class Solution011 { 10 | 11 | public int longestConsecutive(int[] nums) { 12 | // 创建成集合 13 | Set set = new HashSet<>(nums.length, 1); 14 | for (int num : nums) { 15 | set.add(num); 16 | } 17 | 18 | int max = 0; 19 | for (int num : nums) { 20 | // 如果有比它小的,这里就不计算,交给后面的 21 | if (set.contains(num - 1)) { 22 | continue; 23 | } 24 | int count = 1; 25 | while (set.contains(num + 1)) { 26 | num++; 27 | count++; 28 | } 29 | max = Math.max(max, count); 30 | } 31 | 32 | return max; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0129/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0129; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/ 7 | */ 8 | public class Solution { 9 | 10 | public int sumNumbers(TreeNode root) { 11 | return this.sum(root, 0); 12 | } 13 | 14 | public int sum(TreeNode node, int baseVal) { 15 | if (node == null) { 16 | return 0; 17 | } 18 | 19 | baseVal = baseVal * 10 + node.val; 20 | if (node.left == null && node.right == null) { 21 | return baseVal; 22 | } 23 | return this.sum(node.left, baseVal) 24 | + this.sum(node.right, baseVal); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0133/Node.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0133; 2 | 3 | import java.util.List; 4 | 5 | class Node { 6 | 7 | public int val; 8 | public List neighbors; 9 | 10 | public Node() { 11 | } 12 | 13 | public Node(int _val, List _neighbors) { 14 | val = _val; 15 | neighbors = _neighbors; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0133/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0133; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/clone-graph/ 7 | * 8 | * DFS 递归实现。 9 | * 10 | * 当然,也可以使用 BFS 实现。 11 | */ 12 | public class Solution { 13 | 14 | private Map cloneNodes = new HashMap<>(); 15 | 16 | public Node cloneGraph(Node node) { 17 | // 判断是否访问过 18 | Node cloneNode = cloneNodes.get(node); 19 | if (cloneNode != null) { 20 | return cloneNode; 21 | } 22 | // 创建克隆的 node 23 | cloneNode = new Node(node.val, new ArrayList<>()); 24 | cloneNodes.put(node, cloneNode); 25 | 26 | // 遍历节点 27 | for (Node neighbor : node.neighbors) { 28 | cloneNode.neighbors.add(this.cloneGraph(neighbor)); 29 | } 30 | return cloneNode; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0136/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0136; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/single-number/ 5 | * 6 | * 位操作 7 | * 8 | * 考核 ^ 异或运算符 https://blog.csdn.net/kybd2006/article/details/3727218 9 | */ 10 | public class Solution { 11 | 12 | public int singleNumber(int[] nums) { 13 | int result = 0; 14 | for (int num : nums) { 15 | result ^= num; 16 | } 17 | return result; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0139/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0139; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/word-break/ 7 | * 8 | * 动态规划 9 | * 10 | * dp[i] = dp[i] | dp[i - string.length] 11 | * 12 | * 不断遍历 s 字符串,判断 wordDict 往前找,是否有匹配成功的。 13 | */ 14 | public class Solution { 15 | 16 | public boolean wordBreak(String s, List wordDict) { 17 | // 初始化 dp 数组 18 | boolean[] dp = new boolean[s.length() + 1]; 19 | dp[0] = true; // 无字符串,满足可以匹配。 20 | 21 | // dp 开始 22 | for (int i = 1; i <= s.length(); i++) { // 第 i 个字符,存储在 dp[i] ,会有 1 的偏移。 23 | for (String word : wordDict) { 24 | int length = word.length(); 25 | if (length > i) { 26 | continue; 27 | } 28 | // 如果之前位置不符合,则不进行匹配字符串 29 | if (!dp[i - length]) { 30 | continue; 31 | } 32 | // 匹配字符串 33 | String target = s.substring(i - length, i); 34 | if (target.equals(word)) { 35 | dp[i] = true; 36 | break; 37 | } 38 | } 39 | } 40 | return dp[s.length()]; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0141/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0141; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0141/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0141; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * 哈希表 8 | * 9 | * 可以认为是 {@link Solution} 的优化方法 10 | */ 11 | public class Solution02 { 12 | 13 | public boolean hasCycle(ListNode head) { 14 | return detectCycle(head) != null; 15 | } 16 | 17 | public ListNode detectCycle(ListNode head) { 18 | if (head == null) { 19 | return null; 20 | } 21 | Set visited = new HashSet<>(); 22 | while (head != null && head.next != null) { 23 | visited.add(head); 24 | // 如果下一个,已经被访问过,说明存在回环 25 | if (visited.contains(head.next)) { 26 | return head.next; 27 | } 28 | head = head.next; 29 | } 30 | return null; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0142/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0142; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0142/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0142; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/linked-list-cycle-ii/ 5 | * 6 | * 弗洛伊德的乌龟和兔子 7 | * 8 | * 参考博客:https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/ 9 | */ 10 | public class Solution { 11 | 12 | private ListNode getIntersect(ListNode head) { 13 | ListNode slow = head; 14 | ListNode fast = head; 15 | while (fast != null && fast.next != null) { 16 | slow = slow.next; 17 | fast = fast.next.next; 18 | if (slow == fast) { 19 | return slow; 20 | } 21 | } 22 | return null; 23 | } 24 | 25 | public ListNode detectCycle(ListNode head) { 26 | if (head == null) { 27 | return null; 28 | } 29 | 30 | // 先使用快慢指针,找到想交的节点 31 | ListNode intersect = getIntersect(head); 32 | if (intersect == null) { // 如果为空,说明不存在环 33 | return null; 34 | } 35 | 36 | // 找到环的入口 37 | ListNode ptr1 = head; 38 | ListNode ptr2 = intersect; 39 | while (ptr1 != ptr2) { 40 | ptr1 = ptr1.next; 41 | ptr2 = ptr2.next; 42 | } 43 | 44 | return ptr1; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0144/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0144; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/binary-tree-preorder-traversal/ 10 | * 11 | * 递归 12 | */ 13 | public class Solution { 14 | 15 | private List results = new ArrayList<>(); 16 | 17 | public List preorderTraversal(TreeNode root) { 18 | this.recursion(root); 19 | 20 | return this.results; 21 | } 22 | 23 | public void recursion(TreeNode node) { 24 | if (node == null) { 25 | return; 26 | } 27 | 28 | // 当前节点 29 | this.visit(node); 30 | 31 | // 左节点 32 | this.recursion(node.left); 33 | // 右节点 34 | this.recursion(node.right); 35 | } 36 | 37 | private void visit(TreeNode node) { 38 | this.results.add(node.val); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0144/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0144; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Stack; 9 | 10 | /** 11 | * 迭代 12 | */ 13 | public class Solution02 { 14 | 15 | public List preorderTraversal(TreeNode root) { 16 | if (root == null) { 17 | return Collections.emptyList(); 18 | } 19 | 20 | List results = new ArrayList<>(); 21 | Stack stack = new Stack<>(); 22 | stack.add(root); 23 | 24 | while (!stack.isEmpty()) { 25 | TreeNode node = stack.pop(); 26 | results.add(node.val); 27 | // 添加右、左节点 28 | if (node.right != null) { 29 | stack.add(node.right); 30 | } 31 | if (node.left != null) { 32 | stack.add(node.left); 33 | } 34 | } 35 | 36 | return results; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0145/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0145; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/binary-tree-postorder-traversal/ 10 | * 11 | * 递归 12 | */ 13 | public class Solution { 14 | 15 | private List results = new ArrayList<>(); 16 | 17 | public List postorderTraversal(TreeNode root) { 18 | this.recursion(root); 19 | 20 | return this.results; 21 | } 22 | 23 | public void recursion(TreeNode node) { 24 | if (node == null) { 25 | return; 26 | } 27 | 28 | // 左节点 29 | this.recursion(node.left); 30 | // 右节点 31 | this.recursion(node.right); 32 | 33 | // 当前节点 34 | this.visit(node); 35 | } 36 | 37 | private void visit(TreeNode node) { 38 | this.results.add(node.val); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0145/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0145; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Stack; 9 | 10 | /** 11 | * 迭代 12 | * 13 | * 左右中 = 中右左的逆转 14 | */ 15 | public class Solution02 { 16 | 17 | public List postorderTraversal(TreeNode root) { 18 | if (root == null) { 19 | return Collections.emptyList(); 20 | } 21 | 22 | List results = new ArrayList<>(); 23 | Stack stack = new Stack<>(); 24 | stack.add(root); 25 | while (!stack.isEmpty()) { 26 | // 当前节点 27 | TreeNode node = stack.pop(); 28 | results.add(node.val); 29 | // 左右节点。虽然遍历是中右左,但是 stack 是先进后出,所以添加是左右的顺序 30 | if (node.left != null) { 31 | stack.add(node.left); 32 | } 33 | if (node.right != null) { 34 | stack.add(node.right); 35 | } 36 | } 37 | 38 | Collections.reverse(results); 39 | return results; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0148/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0148; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0153/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0153; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/ 5 | * 6 | * 参考博客:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/solution/xun-zhao-xuan-zhuan-pai-lie-shu-zu-zhong-de-zui-xi/ 7 | */ 8 | public class Solution { 9 | 10 | public int findMin(int[] nums) { 11 | if (nums.length == 0) { 12 | return -1; 13 | } 14 | if (nums.length == 1) { 15 | return nums[0]; 16 | } 17 | 18 | // 判断是否是递增的 19 | if (nums[0] < nums[nums.length - 1]) { 20 | return nums[0]; 21 | } 22 | 23 | // 变形的二分查找 24 | int low = 0, high = nums.length - 1; 25 | while (low <= high) { 26 | int mid = low + ((high - low) >> 1); 27 | if (nums[mid] > nums[mid + 1]) { 28 | return nums[mid + 1]; 29 | } 30 | if (nums[low] > nums[mid]) { 31 | high = mid - 1; 32 | } else { 33 | low = mid + 1; 34 | } 35 | } 36 | 37 | throw new IllegalArgumentException("不存在该情况!"); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0155/MinStack.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0155; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/min-stack/ 8 | * 9 | * 暴力 10 | */ 11 | public class MinStack { 12 | 13 | private List stack = new ArrayList<>(); 14 | 15 | private int min = Integer.MAX_VALUE; 16 | 17 | /** initialize your data structure here. */ 18 | public MinStack() { 19 | 20 | } 21 | 22 | public void push(int x) { 23 | stack.add(x); 24 | 25 | if (x < min) { 26 | min = x; 27 | } 28 | } 29 | 30 | public void pop() { 31 | int top = stack.remove(stack.size() - 1); 32 | if (top != min) { 33 | return; 34 | } 35 | 36 | // 重新求最小值 37 | min = Integer.MAX_VALUE; 38 | for (int x : stack) { 39 | if (x < min) { 40 | min = x; 41 | } 42 | } 43 | } 44 | 45 | public int top() { 46 | return stack.get(stack.size() - 1); 47 | } 48 | 49 | public int getMin() { 50 | return min; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0160/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0160; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.ListNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ 7 | * 8 | * 双指针法,比较巧妙,参考博客:https://www.cnblogs.com/grandyang/p/4128461.html 9 | * 两个指针,分别走自己对应的 A、B 节点,然后,走到尾部后,走对方的节点。要么走到相交点相交,要么走到末尾 null 相交。 10 | * 11 | * 另外,还有两种相对一般的方法 12 | * 1. 暴力法 13 | * 2. 哈希表 14 | */ 15 | public class Solution { 16 | 17 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 18 | if (headA == null || headB == null) { 19 | return null; 20 | } 21 | 22 | ListNode pa = headA, pb = headB; 23 | while (pa != pb) { 24 | pa = (pa != null) ? pa.next : headB; 25 | pb = (pb != null) ? pb.next : headA; 26 | } 27 | 28 | return pa; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0162/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0162; 2 | 3 | public class Solution02 { 4 | 5 | public int findPeakElement(int[] nums) { 6 | for (int i = 0; i < nums.length - 1; i++) { 7 | if (nums[i] > nums[i + 1]) 8 | return i; 9 | } 10 | 11 | // 如果都没符合,说明末尾就是尾巴 12 | return nums.length - 1; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0167/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0167; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted 5 | */ 6 | public class Solution { 7 | 8 | public int[] twoSum(int[] numbers, int target) { 9 | int left = 0, right = numbers.length - 1; 10 | while (left < right) { 11 | int sum = numbers[left] + numbers[right]; 12 | if (sum == target) { 13 | return new int[]{left + 1, right + 1}; 14 | } 15 | if (sum > target) { 16 | right--; 17 | } else { 18 | left++; 19 | } 20 | } 21 | 22 | return new int[]{-1, -1}; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0169/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0169; 2 | 3 | /** 4 | * Boyer-Moore 投票算法 5 | * 6 | * 参考博客:https://leetcode-cn.com/problems/majority-element/solution/qiu-zhong-shu-by-leetcode-2/ 方法六。 7 | * 8 | * 比较巧妙的方法 9 | * 10 | * 1. 假设众数作为 1 ,非众数作为 -1 ,则累加后,结果会是 > 0 。 11 | * 2. 每次 count 为 0 时候,我们会选择当前数字作为候选的众数,向下求和。 12 | * 可能候选的众数,实际不是众数,但是最终我们会求到众数。 13 | * 14 | * 理解起来会比较抽象,可以自己模拟下。例如说,n 1 0 n n 。 15 | */ 16 | public class Solution02 { 17 | 18 | public int majorityElement(int[] nums) { 19 | int count = 0; 20 | Integer candidate = null; 21 | for (int num : nums) { 22 | if (count == 0) { 23 | candidate = num; 24 | } 25 | count += (num == candidate) ? 1 : -1; 26 | } 27 | return candidate; 28 | } 29 | 30 | public static void main(String[] args) { 31 | Solution02 solution = new Solution02(); 32 | System.out.println(solution.majorityElement(new int[]{2, 1, 2})); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0189/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0189; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/rotate-array/ 5 | * 6 | * 使用反转,有点巧妙。 7 | * 参考 https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/ 方法四 8 | */ 9 | public class Solution { 10 | 11 | public void rotate(int[] nums, int k) { 12 | // 先去掉多余的移动次数 13 | k = k % nums.length; 14 | // 整个反转 15 | this.swap(nums, 0, nums.length - 1); 16 | // 反转前 k 个 17 | this.swap(nums, 0, k - 1); 18 | // 反转后 k - n 个 19 | this.swap(nums, k, nums.length - 1); 20 | } 21 | 22 | private void swap(int[] nums, int start, int end) { 23 | while (start < end) { 24 | // 交换 25 | int tmp = nums[start]; 26 | nums[start] = nums[end]; 27 | nums[end] = tmp; 28 | // 前后修改 29 | start++; 30 | end--; 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0189/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0189; 2 | 3 | /** 4 | * 使用环状替代 5 | * 6 | * 参考 https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/ 方法三 7 | */ 8 | public class Solution02 { 9 | 10 | public void rotate(int[] nums, int k) { 11 | k = k % nums.length; 12 | int count = 0; 13 | for (int start = 0; count < nums.length; start++) { 14 | int current = start; 15 | int prev = nums[start]; 16 | do { 17 | // 计算下一个节点 18 | int next = (current + k) % nums.length; 19 | // 临时存储下一个节点的值 20 | int tmp = nums[next]; 21 | // 下一个节点,修改成前一个节点的值 22 | nums[next] = prev; 23 | // 记录 prev 为当前节点的值 24 | prev = tmp; 25 | // 设置下一个节点 26 | current = next; 27 | // 计数++ 28 | count++; 29 | } while (current != start); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0190/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0190; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/reverse-bits/ 5 | * 6 | * 位操作 7 | */ 8 | public class Solution { 9 | 10 | public int reverseBits(int n) { 11 | int result = 0; 12 | for (int i = 0; i < 32; i++) { 13 | result = (result << 1) | (n & 1); 14 | n = n >> 1; 15 | } 16 | return result; 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution solution = new Solution(); 21 | // solution.reverseBits(43261596); 22 | System.out.println(solution.reverseBits(43261596)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0191/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0191; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/number-of-1-bits/ 5 | * 6 | * 位操作 7 | * 8 | * n & (n - 1) 操作 9 | * 10 | * 1 :1 & 0 = 0 11 | * 2 :10 & 01 = 0 12 | * 3 :11 & 10 = 10 13 | */ 14 | public class Solution { 15 | 16 | public int hammingWeight(int n) { 17 | int weight = 0; 18 | while (n != 0) { 19 | // 清除最低的 1 。 20 | n = n & (n - 1); 21 | // 增加 22 | weight++; 23 | } 24 | return weight; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0191/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0191; 2 | 3 | /** 4 | * 注意,这个做法,处理负数,会有问题。所以看 {@link Solution03} 5 | * 6 | * 无法通过。 7 | */ 8 | public class Solution02 { 9 | 10 | // you need to treat n as an unsigned value 11 | public int hammingWeight(int n) { 12 | int weight = 0; 13 | 14 | // 计算有多少个 0 15 | while (n != 0) { 16 | if (n % 2 == 1) { 17 | weight++; 18 | // System.out.print(1); 19 | } else { 20 | // System.out.print(0); 21 | } 22 | n = n / 2; 23 | } 24 | 25 | return weight; 26 | } 27 | 28 | public static void main(String[] args) { 29 | int n = 0b11111111000000001111111100000000; 30 | System.out.println(new Solution02().hammingWeight(n)); 31 | // System.out.println(new Solution02().hammingWeight(-3)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0191/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0191; 2 | 3 | public class Solution03 { 4 | 5 | public int hammingWeight(int n) { 6 | int mask = 1; 7 | int weight = 0; 8 | 9 | for (int i = 0; i < 32; i++) { // 32 的原因是,int 是 32 位。 10 | if ((n & mask) == mask) { // 其它位都被 & 掉后,直接等于 mask 了,如果当前位是 1 的话 ,或者换个写法 (n & mask) != 0 11 | weight++; 12 | } 13 | mask = mask << 1; // 左移一位,准备和下一位对比 14 | } 15 | 16 | return weight; 17 | } 18 | 19 | public static void main(String[] args) { 20 | // int n = 0b11111111000000001111111100000000; 21 | // System.out.println(new Solution03().hammingWeight(n)); 22 | // System.out.println(new Solution03().hammingWeight(3)); 23 | // System.out.println(new Solution03().hammingWeight(-3)); 24 | System.out.println(new Solution03().hammingWeight(Integer.MIN_VALUE)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0198/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0198; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/house-robber/ 5 | * 6 | * 动态规划 7 | * 8 | * dp2 = Math.max(dp0 + nums[i], dp1); 9 | */ 10 | public class Solution { 11 | 12 | public int rob(int[] nums) { 13 | int dp0 = 0; 14 | int dp1 = 0; 15 | for (int i = 0; i < nums.length; i++) { 16 | // 计算使用 nums[i] 的情况下的最大值 17 | int dp2 = Math.max(dp0 + nums[i], dp1); 18 | // 设置新的 dp0、dp1 19 | dp0 = dp1; 20 | dp1 = dp2; 21 | } 22 | return dp1; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0200/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0200; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/number-of-islands/ 5 | * 6 | * DFS 7 | * 8 | * 当然,也可以 BFS 。在 9 | */ 10 | public class Solution { 11 | 12 | public int numIslands(char[][] grid) { 13 | int counts = 0; 14 | 15 | for (int i = 0; i < grid.length; i++) { 16 | for (int j = 0; j < grid[0].length; j++) { 17 | if (grid[i][j] == '0') { 18 | continue; 19 | } 20 | if (grid[i][j] == '1') { 21 | counts++; 22 | this.dfs(grid, i, j); 23 | } 24 | } 25 | } 26 | 27 | return counts; 28 | } 29 | 30 | // 将已经选中的,标记 31 | private void dfs(char[][] grid, int i, int j) { 32 | if (i < 0 || i >= grid.length 33 | || j < 0 || j >= grid[0].length) { 34 | return; 35 | } 36 | if (grid[i][j] == '0') { 37 | return; 38 | } 39 | grid[i][j] = '0'; 40 | this.dfs(grid, i + 1, j); 41 | this.dfs(grid, i - 1, j); 42 | this.dfs(grid, i, j + 1); 43 | this.dfs(grid, i, j - 1); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0206/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0206; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0206/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0206; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/reverse-linked-list/ 5 | * 6 | * 参考博客:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/ 7 | */ 8 | class Solution { 9 | 10 | public ListNode reverseList(ListNode head) { 11 | // last ,指向最后遍历到的头节点 12 | ListNode last = null; 13 | // 开始从头节点 head 遍历 14 | while (head != null) { 15 | // 记录当前的 head 16 | ListNode tmp = head; 17 | // head 跳转到下一个节点 18 | head = head.next; 19 | // 原有 head 指向 20 | tmp.next = last; 21 | // last 指向原有 head 节点 22 | last = tmp; 23 | } 24 | 25 | return last; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0206/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0206; 2 | 3 | /** 4 | * 递归实现 5 | * 6 | * 递归解法,可能有点难理解。胖友可以多画下执行过程,艿艿也卡了很久。 7 | */ 8 | public class Solution02 { 9 | 10 | public ListNode reverseList(ListNode head) { 11 | if (head == null || head.next == null) { 12 | return head; 13 | } 14 | 15 | // 递归 16 | ListNode p = reverseList(head.next); // 这样的递归方式,会返回尾节点 17 | 18 | // 设置下一个节点的指向(下一个节点)为自己(head) 19 | head.next.next = head; 20 | // 自己,指向空,否则会形成环路。这里可以画一画。因为,head 的下一个,本身就指向了 head.next 21 | head.next = null; 22 | 23 | return p; 24 | } 25 | 26 | public static void main(String[] args) { 27 | ListNode head = new ListNode(1); 28 | head.next = new ListNode(2); 29 | head.next.next = new ListNode(3); 30 | head.next.next.next = new ListNode(4); 31 | System.out.println(new Solution02().reverseList(head)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0215/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0215; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/kth-largest-element-in-an-array/ 7 | * 8 | * 快速排序,使用内置库 9 | */ 10 | public class Solution { 11 | 12 | public int findKthLargest(int[] nums, int k) { 13 | Arrays.sort(nums); 14 | 15 | return nums[nums.length - k]; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0215/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0215; 2 | 3 | import java.util.PriorityQueue; 4 | import java.util.Queue; 5 | 6 | /** 7 | * 堆排序 8 | * 9 | * 使用优先级队列,实现小顶堆的效果 10 | */ 11 | public class Solution03 { 12 | 13 | public int findKthLargest(int[] nums, int k) { 14 | Queue queue = new PriorityQueue<>(k); 15 | for (int num : nums) { 16 | if (queue.size() < k) { 17 | queue.add(num); 18 | } else { 19 | if (queue.peek() < num) { 20 | queue.remove(); 21 | queue.add(num); 22 | } 23 | } 24 | } 25 | 26 | return queue.peek(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0217/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0217; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/contains-duplicate/ 8 | */ 9 | public class Solution { 10 | 11 | public boolean containsDuplicate(int[] nums) { 12 | Set set = new HashSet<>(); 13 | for (int num : nums) { 14 | if (!set.add(num)) { 15 | return true; 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution solution = new Solution(); 23 | System.out.println(solution.containsDuplicate(new int[]{1,2,3,1})); 24 | System.out.println(solution.containsDuplicate(new int[]{1,2,3,4})); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0219/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0219; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/contains-duplicate-ii/ 8 | */ 9 | public class Solution { 10 | 11 | public boolean containsNearbyDuplicate(int[] nums, int k) { 12 | Map map = new HashMap<>(); 13 | for (int i = 0; i < nums.length; i++) { 14 | int num = nums[i]; 15 | Integer oldIndex = map.put(num, i); 16 | if (oldIndex != null && i - oldIndex <= k) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0229/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0229; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/majority-element-ii/submissions/ 10 | * 11 | * 哈希表 12 | */ 13 | public class Solution { 14 | 15 | public List majorityElement(int[] nums) { 16 | Map counts = new HashMap<>(); 17 | for (int num : nums) { 18 | counts.compute(num, (key, value) -> value == null ? 1 : value + 1); 19 | } 20 | List result = new ArrayList<>(); 21 | int minCounts = nums.length / 3; 22 | for (Map.Entry entry : counts.entrySet()) { 23 | if (entry.getValue() > minCounts) { 24 | result.add(entry.getKey()); 25 | } 26 | if (result.size() == 2) { 27 | break; 28 | } 29 | } 30 | return result; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0230/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0230; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/ 7 | */ 8 | public class Solution { 9 | 10 | private int cnt = 0; 11 | 12 | public int kthSmallest(TreeNode root, int k) { 13 | return this.dfs(root, k).val; 14 | } 15 | 16 | public TreeNode dfs(TreeNode root, int k) { 17 | if (root == null) { 18 | return null; 19 | } 20 | 21 | // 左节点 22 | TreeNode result = this.dfs(root.left, k); 23 | if (result != null) { 24 | return result; 25 | } 26 | 27 | // 中间节点 28 | cnt++; 29 | if (cnt == k) { 30 | return root; 31 | } 32 | 33 | // 右节点 34 | return this.dfs(root.right, k); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0231/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0231; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/power-of-two/ 5 | * 6 | * 位操作 7 | * 8 | * 不断和 2^n 次方,进行 & 操作,如果等于 n 自己,则符合条件。 9 | */ 10 | public class Solution { 11 | 12 | public boolean isPowerOfTwo(int n) { 13 | if (n <= 0) { 14 | return false; 15 | } 16 | int power = 1; 17 | for (int i = 0; i < 32; i++) { 18 | if ((n & power) == n) { 19 | return true; 20 | } 21 | power = power << 1; // * 2 22 | } 23 | return false; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | // System.out.println(solution.isPowerOfTwo(4)); 29 | System.out.println(solution.isPowerOfTwo(-2147483648)); 30 | for (int i = 0; i <= 16; i++) { 31 | System.out.println(solution.isPowerOfTwo(i)); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0231/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0231; 2 | 3 | /** 4 | * 位操作 5 | * 6 | * 通过 n & (n - 1) 的方式,不断去掉最末位(右边)的 1 。 7 | * 如果超过 1 个 1 ,则说明是非 2 的次方。 8 | */ 9 | public class Solution02 { 10 | 11 | public boolean isPowerOfTwo(int n) { 12 | if (n <= 0) { 13 | return false; 14 | } 15 | int count = 0; 16 | while (n > 0) { 17 | n = n & (n - 1); 18 | count++; 19 | if (count >= 2) { 20 | break; 21 | } 22 | } 23 | return count == 1; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution02 solution = new Solution02(); 28 | // System.out.println(solution.isPowerOfTwo(1)); 29 | // System.out.println(solution.isPowerOfTwo(4)); 30 | // System.out.println(solution.isPowerOfTwo(-2147483648)); 31 | for (int i = 0; i <= 16; i++) { 32 | System.out.println(solution.isPowerOfTwo(i)); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0231/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0231; 2 | 3 | /** 4 | * 位操作 5 | * 6 | * 如果是 2 的次方,则 n & (n - 1) == 0 7 | * 8 | * 性能最优解法 9 | */ 10 | public class Solution03 { 11 | 12 | public boolean isPowerOfTwo(int n) { 13 | return n > 0 14 | && (n & (n - 1)) == 0; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0235/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0235; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/ 7 | * 8 | * 递归 9 | */ 10 | public class Solution { 11 | 12 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 13 | // 比它们大,左子树 14 | if (root.val > p.val 15 | && root.val > q.val) { 16 | return this.lowestCommonAncestor(root.left, p, q); 17 | // 比它们小,右子树 18 | } else if (root.val < p.val 19 | && root.val < q.val) { 20 | return this.lowestCommonAncestor(root.right, p, q); 21 | // 之间,说明是最近祖先 22 | } else { 23 | return root; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0235/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0235; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 迭代 7 | */ 8 | public class Solution02 { 9 | 10 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 11 | while (root != null) { 12 | if (root.val > p.val && root.val > q.val) { // 比它们大,左子树 13 | root = root.left; 14 | } else if (root.val < p.val && root.val < q.val) { // 比它们小,右子树 15 | root = root.right; 16 | // 之间,说明是最近祖先 17 | } else { 18 | return root; 19 | } 20 | } 21 | return null; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0236/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0236; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 11 | if (root == null // 未找到 12 | || root == p || root == q) { // 找到 p 或 q 13 | return root; 14 | } 15 | 16 | // 遍历左右子树 17 | TreeNode left = this.lowestCommonAncestor(root.left, p, q); 18 | TreeNode right = this.lowestCommonAncestor(root.right, p, q); 19 | 20 | // 左子树找不到,说明在右子树 21 | if (left == null) { 22 | return right; 23 | } 24 | // 右子树找不到,说明在左子树 25 | if (right == null) { 26 | return left; 27 | } 28 | // 如果都不在,说明在其父亲的子树下 29 | return root; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0238/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0238; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/product-of-array-except-self/ 7 | * 8 | * 思路,当前数字的结果,等于前面的数字的乘积 * 后面的数字的乘积 9 | */ 10 | public class Solution { 11 | 12 | public int[] productExceptSelf(int[] nums) { 13 | // 从左到右,计算截止 14 | int k = 1; 15 | int[] output = new int[nums.length]; // 先存储,左边的乘积结果 16 | for (int i = 0; i < nums.length; i++) { 17 | output[i] = k; 18 | k = k * nums[i]; 19 | } 20 | 21 | // 从右到左 22 | k = 1; 23 | for (int i = nums.length - 1; i >= 0; i--) { 24 | output[i] = output[i] * k; // 在 * 右边的结果 25 | k = k * nums[i]; 26 | } 27 | 28 | return output; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution solution = new Solution(); 33 | System.out.println(Arrays.toString(solution.productExceptSelf(new int[]{1, 2, 3, 4}))); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0240/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0240; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/search-a-2d-matrix-ii/ 5 | * 6 | * 时间复杂度 O(N + M)。 7 | * 8 | * 另外,这题还有三种解法,可以参考博客 https://leetcode-cn.com/problems/search-a-2d-matrix-ii/solution/sou-suo-er-wei-ju-zhen-ii-by-leetcode-2/ 。 9 | * 当然,相比这种,时间复杂度会更高,想对实现却比较复杂。感兴趣的胖友,可以自己去看看。 10 | */ 11 | public class Solution { 12 | 13 | public boolean searchMatrix(int[][] matrix, int target) { 14 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 15 | return false; 16 | } 17 | int row = 0, col = matrix[0].length - 1; 18 | // 从 row = 0 ,col = matrix[0].length 为起点的原因是,能够保证 19 | // 1. 当 target 比当前位置大时,往下走,row++ 增大自己 20 | // 2. 当 target 比当前位置小时,往左走,col-- 减小自己 21 | while (col >= 0 && row < matrix.length) { 22 | if (matrix[row][col] == target) { 23 | return true; 24 | } 25 | if (target > matrix[row][col]) { 26 | row++; 27 | } else { 28 | col--; 29 | } 30 | } 31 | 32 | return false; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0257/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0257; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/binary-tree-paths/ 10 | */ 11 | public class Solution { 12 | 13 | private List results = new ArrayList<>(); 14 | 15 | public List binaryTreePaths(TreeNode root) { 16 | this.dfs(root, ""); 17 | 18 | return results; 19 | } 20 | 21 | private void dfs(TreeNode node, String str) { 22 | if (node == null) { 23 | return; 24 | } 25 | str += str.length() == 0 ? node.val : "->" + node.val; 26 | 27 | // 根节点,添加到结果 28 | if (node.left == null && node.right == null) { 29 | results.add(str); 30 | return; 31 | } 32 | 33 | this.dfs(node.left, str); 34 | this.dfs(node.right, str); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0266/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0266; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/invert-binary-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public TreeNode invertTree(TreeNode root) { 11 | if (root != null) { 12 | // 交换 13 | TreeNode left = root.left; 14 | root.left = root.right; 15 | root.right = left; 16 | 17 | // 子节点 18 | this.invertTree(root.left); 19 | this.invertTree(root.right); 20 | } 21 | 22 | return root; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0268/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0268; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/missing-number/ 5 | * 6 | * 位操作 7 | * 8 | * 异或操作,再拉一波 9 | */ 10 | public class Solution { 11 | 12 | public int missingNumber(int[] nums) { 13 | int n = nums.length; 14 | // 先顺序来一套 ^ 操作 15 | int result = 0; 16 | for (int i = 0; i <= n; i++) { 17 | result = result ^ i; 18 | } 19 | // 在把 nums 数组,顺序再来一套 ^ 操作 20 | for (int num : nums) { 21 | result = result ^ num; 22 | } 23 | return result; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | // System.out.println(solution.missingNumber(new int[]{3, 0, 1})); 29 | System.out.println(solution.missingNumber(new int[]{9,6,4,2,3,5,7,0,1})); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0278/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0278; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/first-bad-version/ 5 | */ 6 | public class Solution extends VersionControl { 7 | 8 | public int firstBadVersion(int n) { 9 | int left = 1, right = n; 10 | while (left <= right) { 11 | int mid = left + ((right - left) >> 1); 12 | if (isBadVersion(mid)) { 13 | right = mid - 1; 14 | } else { 15 | left = mid + 1; 16 | } 17 | } 18 | 19 | return left; 20 | } 21 | 22 | public static void main(String[] args) { 23 | Solution solution = new Solution(); 24 | System.out.println(solution.firstBadVersion(5)); 25 | System.out.println(solution.firstBadVersion(3)); 26 | System.out.println(solution.firstBadVersion(2126753390)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0278/VersionControl.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0278; 2 | 3 | public class VersionControl { 4 | 5 | boolean isBadVersion(int version) { 6 | if (version >= 4) { 7 | return true; 8 | } else { 9 | return false; 10 | } 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0279/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0279; 2 | 3 | /** 4 | * 动态规划 5 | * 6 | * dp[i] = Math.min(dp[i], dp[i - j * j] + 1) 7 | * for (i) 循环时,会首先认为 dp[i] 为 i ,即所有都是 1 。 8 | */ 9 | public class Solution02 { 10 | 11 | public int numSquares(int n) { 12 | int[] dp = new int[n + 1]; 13 | for (int i = 0; i <= n; i++) { 14 | // 首先假设,全部使用 1 凑出 i 15 | dp[i] = i; 16 | // 顺序使用 j * j 作为平方 17 | for (int j = 1; i - j * j >= 0; j++) { 18 | // 因为前面 dp[i] = i 这段在,所以 dp[i - j * j] 是一定有值的。 19 | dp[i] = Math.min(dp[i], dp[i - j * j] + 1); 20 | } 21 | } 22 | return dp[n]; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0287/Solution01.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0287; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/find-the-duplicate-number/ 5 | * 6 | * 暴力法 7 | * 8 | * 时间复杂度是 O(N^2) 9 | */ 10 | public class Solution01 { 11 | 12 | public int findDuplicate(int[] nums) { 13 | for (int i = 0; i < nums.length; i++) { 14 | for (int j = i + 1; j < nums.length; j++) { 15 | if (nums[i] == nums[j]) { 16 | return nums[i]; 17 | } 18 | } 19 | } 20 | 21 | // 找不到符合的 22 | return -1; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Solution01 solution = new Solution01(); 27 | System.out.println(solution.findDuplicate(new int[]{1 ,3, 4, 2, 2})); 28 | System.out.println(solution.findDuplicate(new int[]{3 ,1, 3, 4, 2})); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0287/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0287; 2 | 3 | /** 4 | * 弗洛伊德的乌龟和兔子(循环检测) 5 | * 6 | * 时间复杂度是 O(N) 7 | * 8 | * 参考博客:https://blog.csdn.net/monkeyduck/article/details/50439840 9 | */ 10 | public class Solution02 { 11 | 12 | public int findDuplicate(int[] nums) { 13 | int slow = nums[0]; // 慢指针(乌龟),走一步 14 | int fast = nums[nums[0]]; // 快指向(兔子),走两步 15 | while (slow != fast) { 16 | slow = nums[slow]; 17 | fast = nums[nums[fast]]; 18 | } 19 | 20 | // 实际上,也可以重用上面的 slow 和 fast 两个变量,不过这样可能会有歧义,所以新定义了变量。 21 | int point1 = 0; // 回归原点 22 | int point2 = slow; // 指向慢指针的位置。 23 | while (point1 != point2) { 24 | point1 = nums[point1]; 25 | point2 = nums[point2]; 26 | } 27 | 28 | // 找不到符合的 29 | return point1; 30 | } 31 | 32 | public static void main(String[] args) { 33 | Solution02 solution = new Solution02(); 34 | System.out.println(solution.findDuplicate(new int[]{1 ,3, 4, 2, 2})); 35 | System.out.println(solution.findDuplicate(new int[]{3 ,1, 3, 4, 2})); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0287/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0287; 2 | 3 | /** 4 | * 二分查找法 5 | * 6 | * 时间复杂度是 O(N logN) ,计算方式是,二分是 0(logN) ,然后每个二分,遍历数组,是 N ,所以相乘的结果就是 O(N logN) 。 7 | * 8 | * 参考博客:https://leetcode-cn.com/problems/find-the-duplicate-number/solution/er-fen-fa-si-lu-ji-dai-ma-python-by-liweiwei1419/ 9 | */ 10 | public class Solution03 { 11 | 12 | public int findDuplicate(int[] nums) { 13 | int left = 1; 14 | int right = nums.length; 15 | while (left <= right) { 16 | int mid = left + ((right - left) >> 1); 17 | // 计算小于 mid 的数值 18 | int counts = 0; 19 | for (int num : nums) { 20 | if (num <= mid) { 21 | counts++; 22 | } 23 | } 24 | // 计算折半 25 | if (counts > mid) { // 超过 mid ,说明重复在左半区,缩小 26 | right = mid - 1; 27 | } else { // <= mid ,说明重复在右半区,放大 28 | left = mid + 1; 29 | } 30 | } 31 | 32 | return left; 33 | } 34 | 35 | public static void main(String[] args) { 36 | Solution03 solution = new Solution03(); 37 | System.out.println(solution.findDuplicate(new int[]{1 ,2, 2, 4})); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0303/NumArray.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0303; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/range-sum-query-immutable/ 5 | * 6 | * 数组 7 | */ 8 | public class NumArray { 9 | 10 | private int[] nums; 11 | 12 | public NumArray(int[] nums) { 13 | this.nums = nums; 14 | } 15 | 16 | public int sumRange(int i, int j) { 17 | int sum = 0; 18 | for (int k = i; k <= j; k++) { 19 | sum += nums[k]; 20 | } 21 | return sum; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0303/NumArray02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0303; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/range-sum-query-immutable/ 5 | * 6 | * {@link #sums} 缓存 7 | * 8 | * 也算动态规划把。 9 | * 10 | * sums[i, j] = sums[0, j] - sums[0, i - 1] 。 11 | * 12 | * 进一步优化的话,就是把构造方法里的提前计算缓存,变成后置计算。 13 | */ 14 | public class NumArray02 { 15 | 16 | private int[] sums; // 记录使用从 0 到 i 位置,求和。注意,第 0 位为空。 17 | 18 | public NumArray02(int[] nums) { 19 | // 计算 sums 20 | this.sums = new int[nums.length + 1]; 21 | for (int i = 0; i < nums.length; i++) { 22 | sums[i + 1] = sums[i] + nums[i]; 23 | } 24 | } 25 | 26 | public int sumRange(int i, int j) { 27 | return sums[j + 1] - sums[i]; 28 | } 29 | 30 | public static void main(String[] args) { 31 | NumArray02 array = new NumArray02(new int[]{-2,0,3,-5,2,-1}); 32 | System.out.println(array.sumRange(0, 2)); // 1 33 | System.out.println(array.sumRange(2, 5)); // -1 34 | System.out.println(array.sumRange(0, 5)); // -3 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0309/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0309; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ 5 | * 6 | * 动态规划 7 | * 8 | * 不持有股票 sell[i] = Math.max(sell[i - 1], cooldown[i]); 9 | * 冷冻期 cooldown[i] = Math.max(cooldown[i - 1], buy[i] + nums[i]); 10 | * 持有一个股票 buy[i] = Math.max(buy[i - 1], sell[i - 1] - nums[i]); 11 | * 12 | * 可以进一步压缩,不使用数组,每一轮使用一套变量,然后赋值。 13 | */ 14 | public class Solution { 15 | 16 | public int maxProfit(int[] prices) { 17 | if (prices.length == 0) { 18 | return 0; 19 | } 20 | int sell = 0; 21 | int cooldown = 0; 22 | int buy = -prices[0]; 23 | 24 | // dp 开始 25 | for (int i = 1; i < prices.length; i++) { 26 | // 本轮计算 27 | int price = prices[i]; 28 | int sellNow = Math.max(sell, cooldown); 29 | int cooldownNow = Math.max(cooldown, buy + price); 30 | int buyNow = Math.max(buy, sell - price); 31 | // 赋值 32 | sell = sellNow; 33 | cooldown = cooldownNow; 34 | buy = buyNow; 35 | } 36 | return Math.max(sell, cooldown); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0337/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0337; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/house-robber-iii/ 7 | * 8 | * 暴力 DFS 递归 9 | * 10 | * 因为存在重复访问,所以效率低 11 | */ 12 | public class Solution { 13 | 14 | public int rob(TreeNode root) { 15 | // root 为空的情况 16 | if (root == null) { 17 | return 0; 18 | } 19 | 20 | // 计算使用当前节点,和排序其子节点 21 | int value1 = root.val; 22 | if (root.left != null) { 23 | value1 += this.rob(root.left.left) + this.rob(root.left.right); 24 | } 25 | if (root.right != null) { 26 | value1 += this.rob(root.right.left) + this.rob(root.right.right); 27 | } 28 | 29 | // 不使用当前节点 30 | int value2 = this.rob(root.left) + this.rob(root.right); 31 | 32 | return Math.max(value1, value2); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0337/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0337; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 动态规划 7 | * 8 | * 参考博客:https://leetcode-cn.com/problems/house-robber-iii/solution/java-2ms-by-horanol/ 9 | */ 10 | public class Solution02 { 11 | 12 | public int rob(TreeNode root) { 13 | int[] results = this.doRob(root); 14 | return Math.max(results[0], results[1]); 15 | } 16 | 17 | private int[] doRob(TreeNode root) { 18 | // results[0] 包含当前节点 root 的最大值 19 | // results[1] 不包含当前节点 root 的最大值 20 | int[] results = new int[2]; 21 | 22 | // 节点为空的情况 23 | if (root == null) { 24 | return results; 25 | } 26 | 27 | // 左子树,包含左节点和不包含左节点的最大值。 28 | int[] lefts = this.doRob(root.left); 29 | // 右子树,同上 30 | int[] rights = this.doRob(root.right); 31 | 32 | // 计算当前节点,包含和不包含的最大值。 33 | results[1] = Math.max(lefts[0], lefts[1]) + Math.max(rights[0], rights[1]); 34 | results[0] = root.val + lefts[1] + rights[1]; 35 | return results; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0338/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0338; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/counting-bits/ 5 | * 6 | * 位操作 7 | */ 8 | public class Solution { 9 | 10 | public int[] countBits(int num) { 11 | int[] bits = new int[num + 1]; 12 | for (int i = 1; i <= num; i++) { 13 | bits[i] = 1 + bits[i & (i - 1)]; 14 | } 15 | return bits; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0338/Solution01.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0338; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Solution01 { 6 | 7 | public int[] countBits(int num) { 8 | int[] results = new int[num + 1]; 9 | results[0] = 0; 10 | 11 | // 计算每个位置的 bits 数量 12 | for (int i = 1; i <= num; i++) { 13 | int bits = i & 1; // 计算最后一位,是否为负数 14 | results[i] = bits + results[i >> 1]; 15 | } 16 | 17 | return results; 18 | } 19 | 20 | public static void main(String[] args) { 21 | System.out.println(Arrays.toString(new Solution01().countBits(5))); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0342/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0342; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/power-of-four/ 5 | * 6 | * 位操作 7 | * 8 | * 1 =》00001 9 | * 4 =》00100 10 | * 8 =》10000 11 | */ 12 | public class Solution { 13 | 14 | public boolean isPowerOfFour(int num) { 15 | if (num <= 0) { 16 | return false; 17 | } 18 | // 如果是 4 进制,必须满足 2 进制。 19 | if ((num & (num - 1)) != 0) { // 注意,如果不判断 20 | return false; 21 | } 22 | // 奇数位置,都是 1 。 23 | if ((num & 0b01010101010101010101010101010101) == num) { 24 | return true; 25 | } 26 | return false; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0343/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0343; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/integer-break 5 | * 6 | * 动态规划 7 | * 8 | * 表达式 dp[i] = Math.max(dp[i - j] * j, dp[i]) 9 | */ 10 | public class Solution { 11 | 12 | public int integerBreak(int n) { 13 | // 因为必须分解成对应的数字 14 | if (n == 2) { 15 | return 1; 16 | } 17 | if (n == 3) { 18 | return 3; 19 | } 20 | 21 | // DP 开始 22 | int[] dp = new int[n + 1]; 23 | for (int i = 0; i <= n; i++) { 24 | dp[i] = i; 25 | } 26 | for (int i = 2; i <= n; i++) { 27 | for (int j = 1; j < i; j++) { 28 | dp[i] = Math.max(dp[i - j] * j, dp[i]); 29 | } 30 | } 31 | return dp[n]; 32 | } 33 | 34 | public static void main(String[] args) { 35 | Solution solution = new Solution(); 36 | System.out.println(solution.integerBreak(3)); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0343/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0343; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/integer-break 5 | * 6 | * 动态规划 7 | * 8 | * 和 {@link Solution} 类似,简化逻辑 9 | * 10 | * 表达式 dp[i] = Math.max(dp[i - j] * j, dp[i], (i - j) * j) 11 | */ 12 | public class Solution02 { 13 | 14 | public int integerBreak(int n) { 15 | // DP 开始 16 | int[] dp = new int[n + 1]; 17 | dp[1] = 1; 18 | for (int i = 2; i <= n; i++) { 19 | for (int j = 1; j < i; j++) { 20 | dp[i] = this.max(dp[i - j] * j, dp[i], (i - j) * j); 21 | } 22 | } 23 | return dp[n]; 24 | } 25 | 26 | private int max(int a, int b, int c) { 27 | return Math.max(Math.max(a, b), c); 28 | } 29 | 30 | public static void main(String[] args) { 31 | Solution02 solution = new Solution02(); 32 | // System.out.println(solution.integerBreak(3)); 33 | // System.out.println(solution.integerBreak(2)); 34 | System.out.println(solution.integerBreak(10)); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0343/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0343; 2 | 3 | /** 4 | * TODO 更多解法 5 | * 6 | * https://leetcode-cn.com/problems/integer-break/solution/tan-xin-xuan-ze-xing-zhi-de-jian-dan-zheng-ming-py/ 7 | */ 8 | public class SolutionX { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0344/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0344; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/reverse-string/ 5 | */ 6 | public class Solution { 7 | 8 | public void reverseString(char[] s) { 9 | int left = 0, right = s.length - 1; 10 | while (left < right) { 11 | // swap 12 | char tmp = s[left]; 13 | s[left] = s[right]; 14 | s[right] = tmp; 15 | // 互相靠近 16 | left++; 17 | right--; 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0367/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0367; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/valid-perfect-square/ 5 | * 6 | * 二分查找 7 | */ 8 | public class Solution { 9 | 10 | public boolean isPerfectSquare(int num) { 11 | if (num <= 1) { 12 | return true; 13 | } 14 | 15 | int left = 1, right = num / 2; 16 | while (left <= right) { 17 | int mid = left + ((right - left) >> 1); 18 | int result = num / mid; 19 | if (mid == result) { 20 | right = mid; 21 | break; 22 | } 23 | if (result > mid) { 24 | left = mid + 1; 25 | } else { 26 | right = mid - 1; 27 | } 28 | } 29 | 30 | return right * right == num; 31 | } 32 | 33 | public static void main(String[] args) { 34 | Solution solution = new Solution(); 35 | // solution.isPerfectSquare(4); 36 | for (int i = 0; i <= 100; i ++) { 37 | System.out.println(i + "\t" + solution.isPerfectSquare(i)); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0371/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0371; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/sum-of-two-integers/ 5 | * 6 | * 位操作 7 | * 8 | * 这个实现,真的是牛逼啊! 9 | */ 10 | public class Solution { 11 | 12 | public int getSum(int a, int b) { 13 | // 1、a ^ b ,每一位,求和。 0 0 得 0 ,0 1 得 1 ,1 1 得 0(需要进位) 14 | // 2.1、a & b ,每一位,进位。0 0 得 0 ,0 1 得 0 ,1 1 得 1 。 15 | // 2.2、((a & b) << 1) ,进位左移,这样就可以进位累加。继续递归 16 | // 3、b == 0 ,当 b 等于 0 ,说明,已经累加全部完毕。 17 | return b == 0 ? a : this.getSum(a ^ b, ((a & b) << 1)); 18 | } 19 | 20 | public static void main(String[] args) { 21 | Solution solution = new Solution(); 22 | System.out.println(solution.getSum(1, 2)); 23 | System.out.println(solution.getSum(-2, 3)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0377/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0377; 2 | 3 | /** 4 | * http://leetcode-cn.com/problems/combination-sum-iv/ 5 | * 6 | * 动态规划 7 | * 8 | * dp[i] = dp[i] + dp[i - num] 9 | * 10 | * 其中,i 为指定值。 11 | */ 12 | public class Solution { 13 | 14 | public int combinationSum4(int[] nums, int target) { 15 | int[] dp = new int[target + 1]; 16 | dp[0] = 1; // 0 的话,一定有一个组合 17 | for (int i = 1; i <= target; i++) { 18 | for (int num : nums) { 19 | if (num > i) { 20 | continue; 21 | } 22 | dp[i] = dp[i] + dp[i - num]; 23 | } 24 | } 25 | return dp[target]; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | System.out.println(solution.combinationSum4(new int[]{1, 2, 3}, 4)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0387/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0387; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/first-unique-character-in-a-string/ 9 | * 10 | * 哈希表 11 | */ 12 | public class Solution { 13 | 14 | public int firstUniqChar(String s) { 15 | Map counts = new HashMap<>(); 16 | Map indexes = new LinkedHashMap<>(); 17 | // 计数 + 位置 18 | for (int i = 0; i < s.length(); i++) { 19 | Character ch = s.charAt(i); 20 | counts.put(ch, counts.getOrDefault(ch, 0) + 1); 21 | indexes.putIfAbsent(ch, i); 22 | } 23 | // 遍历获得结果 24 | for (Map.Entry index : indexes.entrySet()) { 25 | if (counts.get(index.getKey()) == 1) { 26 | return index.getValue(); 27 | } 28 | } 29 | return -1; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0392/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0392; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/is-subsequence/ 5 | * 6 | * 贪心算法 7 | * 8 | * 逐个匹配,如果不匹配,则跳过字符 9 | */ 10 | public class Solution { 11 | 12 | public boolean isSubsequence(String s, String t) { 13 | int sIndex = 0; 14 | int tIndex = 0; 15 | while (sIndex < s.length() && tIndex < t.length()) { 16 | char sCh = s.charAt(sIndex); 17 | char tCh = t.charAt(tIndex); 18 | if (sCh == tCh) { 19 | sIndex++; 20 | tIndex++; 21 | continue; 22 | } 23 | tIndex++; 24 | } 25 | return sIndex == s.length(); 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution solution = new Solution(); 30 | // System.out.println(solution.isSubsequence("abc", "ahbgdc")); 31 | // System.out.println(solution.isSubsequence("axc", "ahbgdc")); 32 | // System.out.println(solution.isSubsequence("aaa", "aa")); 33 | System.out.println(solution.isSubsequence("aaa", "aaa")); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0392/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0392; 2 | 3 | /** 4 | * TODO 动态规划 5 | */ 6 | public class SolutionX { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0409/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0409; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/longest-palindrome/ 5 | */ 6 | public class Solution { 7 | 8 | public int longestPalindrome(String s) { 9 | // 计数 10 | int[] counts = new int['z' - 'A' + 1]; 11 | for (char ch : s.toCharArray()) { 12 | counts[ch - 'A']++; 13 | } 14 | 15 | // 计算最长 16 | int longest = 0; 17 | boolean extra = false; 18 | for (int count : counts) { 19 | longest += count / 2; 20 | if (!extra && (count & 1) == 1) { 21 | extra = true; 22 | } 23 | } 24 | 25 | return longest * 2 + (extra ? 1 : 0); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0413/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0413; 2 | 3 | /** 4 | * 动态规划 5 | * 6 | * 表达式 7 | * 8 | * 每个子等差数列,每多一个数字,会多比上一次多 1 的组合。 9 | * 例如说,3 个等差数,组合数为 1 ;4 个等差数,组合数为 2 ;5 个等差数为 3 。 10 | * 11 | * dp = dp + 1 。 12 | */ 13 | public class Solution02 { 14 | 15 | public int numberOfArithmeticSlices(int[] A) { 16 | int sum = 0; // 总计 17 | int dp = 0; 18 | for (int i = 2; i < A.length; i++) { 19 | if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) { 20 | // 21 | dp = dp + 1; 22 | // 23 | sum = sum + dp; 24 | } else { 25 | dp = 0; 26 | } 27 | } 28 | return sum; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0429/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0429; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.Node; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/ 9 | * 10 | * 迭代 11 | */ 12 | public class Solution { 13 | 14 | public List> levelOrder(Node root) { 15 | if (root == null) { 16 | return Collections.emptyList(); 17 | } 18 | 19 | List> results = new ArrayList<>(); 20 | Queue queue = new LinkedList<>(); 21 | queue.add(root); 22 | while (!queue.isEmpty()) { 23 | int counts = queue.size(); 24 | List result = new ArrayList<>(counts); 25 | while (counts > 0) { 26 | counts--; 27 | // Node 28 | Node node = queue.poll(); 29 | result.add(node.val); 30 | // 添加到队列 31 | if (node.children != null) { 32 | queue.addAll(node.children); 33 | } 34 | } 35 | results.add(result); 36 | } 37 | 38 | return results; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0435/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0435; 2 | 3 | /** 4 | * TODO 动态规划 5 | * 6 | * 参考博客 https://leetcode-cn.com/problems/non-overlapping-intervals/solution/wu-zhong-die-qu-jian-by-leetcode/ 7 | */ 8 | public class SolutionX { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0437/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0437; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/path-sum-iii/ 7 | */ 8 | public class Solution { 9 | 10 | private int pathCounts = 0; 11 | 12 | public int pathSum(TreeNode root, int sum) { 13 | this.traverseTreeNode(root, sum); 14 | 15 | return pathCounts; 16 | } 17 | 18 | public void traverseTreeNode(TreeNode root, int sum) { 19 | if (root == null) { 20 | return; 21 | } 22 | 23 | // 从该节点开始,寻找 sum 24 | this.doPathSum(root, sum); 25 | 26 | // 处理左右节点 27 | this.traverseTreeNode(root.left, sum); 28 | this.traverseTreeNode(root.right, sum); 29 | } 30 | 31 | public void doPathSum(TreeNode node, int sum) { 32 | // 排除当前节点为空的情况 33 | if (node == null) { 34 | return; 35 | } 36 | 37 | sum -= node.val; 38 | if (sum == 0) { 39 | pathCounts++; 40 | } 41 | 42 | // 处理左右节点 43 | this.doPathSum(node.left, sum); 44 | this.doPathSum(node.right, sum); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0437/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0437; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 在 {@link Solution} 的方案上,进一步简化 7 | */ 8 | public class Solution02 { 9 | 10 | private int pathCounts = 0; 11 | 12 | public int pathSum(TreeNode root, int sum) { 13 | if (root == null) { 14 | return 0; 15 | } 16 | 17 | return this.doPathSum(root, sum) 18 | + this.pathSum(root.left, sum) 19 | + this.pathSum(root.right, sum); 20 | } 21 | 22 | public int doPathSum(TreeNode node, int sum) { 23 | // 排除当前节点为空的情况 24 | if (node == null) { 25 | return 0; 26 | } 27 | 28 | sum -= node.val; 29 | 30 | // 处理左右节点 31 | return (sum == 0 ? 1 : 0) 32 | + this.doPathSum(node.left, sum) 33 | + this.doPathSum(node.right, sum); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0442/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0442; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/ 8 | */ 9 | @SuppressWarnings("Duplicates") 10 | public class Solution { 11 | 12 | public List findDuplicates(int[] nums) { 13 | for (int i = 0; i < nums.length; i++) { 14 | while (nums[i] != i +1 15 | && nums[i] != nums[nums[i] - 1]) { 16 | swap(nums, i, nums[i] - 1); 17 | } 18 | } 19 | 20 | // 计算重复值 21 | List results = new ArrayList(); 22 | for (int i = 0; i < nums.length; i++) { 23 | // 符合当前位置,直接跳过 24 | if (nums[i] == i + 1) { 25 | continue; 26 | } 27 | results.add(nums[i]); 28 | } 29 | 30 | return results; 31 | } 32 | 33 | private void swap(int[] nums , int i, int j) { 34 | int tmp = nums[i]; 35 | nums[i] = nums[j]; 36 | nums[j] = tmp; 37 | } 38 | 39 | public static void main(String[] args) { 40 | Solution solution = new Solution(); 41 | System.out.println(solution.findDuplicates(new int[]{4, 3, 2, 7, 8, 2, 3, 1})); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0445/ListNode.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0445; 2 | 3 | class ListNode { 4 | int val; 5 | ListNode next; 6 | ListNode(int x) { 7 | val = x; 8 | next = null; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "ListNode{" + 14 | "val=" + val + 15 | '}'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0448/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0448; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/ 8 | */ 9 | public class Solution { 10 | 11 | public List findDisappearedNumbers(int[] nums) { 12 | for (int i = 0; i < nums.length; i++) { 13 | while (nums[i] != i +1 14 | && nums[i] != nums[nums[i] - 1]) { 15 | swap(nums, i, nums[i] - 1); 16 | } 17 | } 18 | 19 | // 计算重复值 20 | List results = new ArrayList(); 21 | for (int i = 0; i < nums.length; i++) { 22 | // 符合当前位置,直接跳过 23 | if (nums[i] == i + 1) { 24 | continue; 25 | } 26 | results.add(i + 1); 27 | } 28 | 29 | return results; 30 | } 31 | 32 | private void swap(int[] nums , int i, int j) { 33 | int tmp = nums[i]; 34 | nums[i] = nums[j]; 35 | nums[j] = tmp; 36 | } 37 | 38 | public static void main(String[] args) { 39 | Solution solution = new Solution(); 40 | System.out.println(solution.findDisappearedNumbers(new int[]{4, 3, 2, 7, 8, 2, 3, 1})); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0454/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0454; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/4sum-ii/ 8 | * 9 | * 哈希表 10 | */ 11 | public class Solution { 12 | 13 | public int fourSumCount(int[] A, int[] B, int[] C, int[] D) { 14 | // 先求,A 和 B 的和的组合 15 | Map sumAB = new HashMap<>(); 16 | for (int a : A) { 17 | for (int b : B) { 18 | int sum = a + b; 19 | sumAB.put(sum, sumAB.getOrDefault(sum, 0) + 1); 20 | } 21 | } 22 | 23 | // 再求,C 和 D 的组合 24 | int counts = 0; 25 | for (int c : C) { 26 | for (int d : D) { 27 | int sum = c + d; 28 | counts += sumAB.getOrDefault(-sum, 0); 29 | } 30 | } 31 | 32 | return counts; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0455/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0455; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/assign-cookies/ 7 | * 8 | * 贪心算法 9 | * 10 | * 从胃口最小的小孩开始发饼干,给能满足它胃口的最小饼干。 11 | */ 12 | public class Solution { 13 | 14 | public int findContentChildren(int[] g, int[] s) { 15 | Arrays.sort(g); 16 | Arrays.sort(s); 17 | // 贪心比较 18 | int gIndex = 0; 19 | int sIndex = 0; 20 | while (sIndex < s.length 21 | && gIndex < g.length) { 22 | // 这个小孩子胃口比较大,准备下一块饼干 23 | if (g[gIndex] > s[sIndex]) { 24 | sIndex++; 25 | continue; 26 | } 27 | // 把这个饼干给这个小孩,然后轮到下一个小孩。 28 | gIndex++; 29 | sIndex++; 30 | } 31 | return gIndex; 32 | } 33 | 34 | public static void main(String[] args) { 35 | Solution solution = new Solution(); 36 | System.out.println(solution.findContentChildren(new int[]{1, 2}, 37 | new int[]{1, 2, 3})); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0461/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0461; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/hamming-distance/ 5 | * 6 | * 位操作 7 | */ 8 | public class Solution { 9 | 10 | public int hammingDistance(int x, int y) { 11 | int distance = 0; 12 | while (x != 0 || y != 0) { 13 | // 取最后一位 14 | if ((x & 1) != (y & 1)) { 15 | distance++; 16 | } 17 | // 去掉最后一位 18 | x = x >> 1; 19 | y = y >> 1; 20 | } 21 | return distance; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | System.out.println(solution.hammingDistance(0, 4)); 27 | // System.out.println(solution.hammingDistance(0, 3)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0474/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0474; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/ones-and-zeroes/ 5 | * 6 | * 动态规划 7 | * 8 | * 表达式,dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones]); 9 | * 10 | * 其中,zeros 和 ones 是当前字符串的 0 和 1 的数量,而 dp[i][j] 表示 i 和 j 个 0 和 1 的情况下,可以满足最多多少个字符串。 11 | */ 12 | public class Solution { 13 | 14 | public int findMaxForm(String[] strs, int m, int n) { 15 | if (m == 0 && n == 0) { 16 | return 0; 17 | } 18 | 19 | int[][] dp = new int[m + 1][n + 1]; 20 | for (String str : strs) { 21 | // 计算 0 和 1 的数量 22 | int zeros = 0; 23 | int ones = 0; 24 | for (int i = 0; i < str.length(); i++) { 25 | if (str.charAt(i) == '0') { 26 | zeros++; 27 | } else { 28 | ones++; 29 | } 30 | } 31 | 32 | // 倒序 dp ,不然会覆盖值。 33 | for (int i = m; i >= zeros; i--) { 34 | for (int j = n; j >= ones; j--) { 35 | dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1); 36 | } 37 | } 38 | } 39 | return dp[m][n]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0476/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0476; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/number-complement/ 5 | * 6 | * 位操作 7 | * 8 | * 逐个位置,通过 ^ 操作取反,并移到对应位置。 9 | */ 10 | public class Solution { 11 | 12 | public int findComplement(int num) { 13 | int result = 0; 14 | int index = 0; 15 | while (num > 0) { 16 | // 取 num 当前最后一位,取反,并移动对应位置 17 | result = (((num & 1) ^ 1) << index) | result; 18 | // 去掉 number 最后一位 19 | num = num >> 1; 20 | // 增加位置 21 | index++; 22 | } 23 | return result; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | System.out.println(solution.findComplement(2)); 29 | System.out.println(solution.findComplement(5)); 30 | System.out.println(solution.findComplement(1)); 31 | System.out.println(solution.findComplement(0)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0476/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0476; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/number-complement/ 5 | * 6 | * 位操作 7 | * 8 | * 寻找最高位的 1 ,然后获得对应的从该位置到最右都是 1 ,这样在异或操作,就可以实现取反了。 9 | */ 10 | public class Solution02 { 11 | 12 | public int findComplement(int num) { 13 | if (num == 0) { // 排除 0 ,不然会死循环。 14 | return 0; 15 | } 16 | // 寻找最高位的 1 。 17 | int mask = 1 << 30; // 不能 << 31 ,不然就是负数了。 18 | while ((mask & num) == 0) { 19 | mask = mask >> 1; 20 | } 21 | 22 | // 求从当前开始,都变成 1 。 23 | mask = (mask << 1) - 1; 24 | 25 | // 异或操作,取反 26 | return num ^ mask; 27 | } 28 | 29 | public static void main(String[] args) { 30 | // Solution02 solution = new Solution02(); 31 | // System.out.println(solution.findComplement(2)); 32 | // System.out.println(solution.findComplement(5)); 33 | // System.out.println(solution.findComplement(1)); 34 | // System.out.println(solution.findComplement(0)); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0485/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0485; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/max-consecutive-ones/ 5 | */ 6 | public class Solution { 7 | 8 | public int findMaxConsecutiveOnes(int[] nums) { 9 | int max = 0; 10 | int counts = 0; // 计数当前序列,有多少个 1 。 11 | for (int num : nums) { 12 | if (num == 0) { 13 | counts = 0; 14 | } else { 15 | // 计数++ 16 | counts++; 17 | // 判断是否最大 18 | if (counts > max) { 19 | max = counts; 20 | } 21 | } 22 | } 23 | return max; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | System.out.println(solution.findMaxConsecutiveOnes(new int[]{1, 1, 0, 1, 1, 1})); 29 | System.out.println(solution.findMaxConsecutiveOnes(new int[]{1, 1, 1, 0, 1, 1})); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0496/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0496; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Stack; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/next-greater-element-i/ 9 | */ 10 | public class Solution { 11 | 12 | public int[] nextGreaterElement(int[] nums1, int[] nums2) { 13 | Map mappings = new HashMap<>(); // key:数字,value:在 num2 中,下一个比它大的值。 14 | Stack stack = new Stack<>(); 15 | // 倒序 num2 数组,计算每个元素比它大的下一个元素 16 | for (int i = nums2.length - 1; i >= 0; i--) { 17 | int num = nums2[i]; 18 | // 移除 stack 中,比 num 小的值 19 | while (!stack.isEmpty() && stack.peek() <= num) { 20 | stack.pop(); 21 | } 22 | 23 | // 添加下一个最大值到 mappings 中 24 | if (!stack.isEmpty()) { 25 | mappings.put(num, stack.peek()); 26 | } 27 | 28 | // 添加到栈中 29 | stack.add(num); 30 | } 31 | 32 | // 获得 num 数组中,每一个大的元素 33 | for (int i = 0; i < nums1.length; i++) { 34 | nums1[i] = mappings.getOrDefault(nums1[i], -1); 35 | } 36 | return nums1; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0509/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0509; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/fibonacci-number/ 5 | * 6 | * 动态规划 7 | */ 8 | public class Solution { 9 | 10 | public int fib(int N) { 11 | if (N == 0) { 12 | return 0; 13 | } 14 | if (N == 1) { 15 | return 1; 16 | } 17 | int f0 = 0; 18 | int f1 = 1; 19 | for (int i = 2; i <= N; i++) { 20 | // 计算当前节点的只 21 | int f2 = f0 + f1; 22 | // 赋值 23 | f0 = f1; 24 | f1 = f2; 25 | } 26 | return f1; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0509/SolutionX.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0509; 2 | 3 | /** 4 | * TODO 芋艿 5 | * 目前还有两种很骚的解法 6 | * 7 | * https://leetcode-cn.com/problems/fibonacci-number/solution/javascriptjie-fa-by-abpvnext/ 8 | * 9 | * 1、斐波那契数列通项公式 10 | * 2、矩阵乘法 (高级) 11 | */ 12 | public class SolutionX { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0513/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0513; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/find-bottom-left-tree-value/ 9 | */ 10 | public class Solution { 11 | 12 | public int findBottomLeftValue(TreeNode root) { 13 | assert root != null; 14 | 15 | // 初始 16 | Queue queue = new LinkedList<>(); 17 | queue.add(root); 18 | TreeNode leftNode = null; 19 | 20 | // 遍历 21 | while (!queue.isEmpty()) { 22 | // 获得 23 | leftNode = queue.peek(); 24 | 25 | // 遍历层级 26 | int count = queue.size(); 27 | for (int i = 0; i < count; i++) { 28 | TreeNode node = queue.poll(); 29 | // 添加到 nodes 中 30 | if (node.left != null) { 31 | queue.add(node.left); 32 | } 33 | if (node.right != null) { 34 | queue.add(node.right); 35 | } 36 | } 37 | } 38 | 39 | return leftNode.val; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0513/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0513; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | /** 9 | * 在 {@link Solution} 优化,先添加右节点,在添加左节点 10 | */ 11 | public class Solution02 { 12 | 13 | public int findBottomLeftValue(TreeNode root) { 14 | assert root != null; 15 | 16 | // 初始 17 | Queue queue = new LinkedList<>(); 18 | queue.add(root); 19 | TreeNode leftNode = null; 20 | 21 | // 遍历 22 | while (!queue.isEmpty()) { 23 | // 获得 24 | leftNode = queue.poll(); 25 | // 添加到 nodes 中 26 | if (leftNode.right != null) { 27 | queue.add(leftNode.right); 28 | } 29 | if (leftNode.left != null) { 30 | queue.add(leftNode.left); 31 | } 32 | } 33 | 34 | return leftNode.val; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0518/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0518; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/coin-change-2/ 5 | * 6 | * 动态规划 7 | * 8 | * dp[i] = dp[i] + dp[i - num] 9 | * 10 | * 不同的是,按照 coins 进行遍历 11 | */ 12 | public class Solution { 13 | 14 | public int change(int amount, int[] coins) { 15 | int[] dp = new int[amount + 1]; 16 | dp[0] = 1; // 0 个硬币,肯定有 1 种换法 17 | for (int coin : coins) { // 注意,基于 coin 遍历,不然会出现重复结果。 18 | for (int i = coin; i <= amount; i++) { 19 | dp[i] = dp[i] + dp[i - coin]; 20 | } 21 | } 22 | return dp[amount]; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Solution solution = new Solution(); 27 | // 1:1 28 | // 2:1、1 ;2 29 | // 3:1、1、1;1、2 30 | // 4:1、1、1、1; 31 | System.out.println(solution.change(5, new int[]{1, 2, 5})); 32 | 33 | System.out.println(solution.change(3, new int[]{2})); 34 | System.out.println(solution.change(10, new int[]{10})); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0530/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0530; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst/ 7 | */ 8 | public class Solution { 9 | 10 | private Integer lastValue; 11 | private int min = Integer.MAX_VALUE; 12 | 13 | public int getMinimumDifference(TreeNode root) { 14 | this.dfs(root); 15 | 16 | return min; 17 | } 18 | 19 | private void dfs(TreeNode node) { 20 | if (node == null) { 21 | return; 22 | } 23 | 24 | // 左节点 25 | this.dfs(node.left); 26 | 27 | // 当前节点 28 | if (this.lastValue != null) { 29 | this.min = Math.min(node.val - this.lastValue, min); 30 | } 31 | this.lastValue = node.val; 32 | 33 | 34 | // 右节点 35 | this.dfs(node.right); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0538/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0538; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/convert-bst-to-greater-tree/ 7 | */ 8 | public class Solution { 9 | 10 | private int sum = 0; 11 | 12 | public TreeNode convertBST(TreeNode root) { 13 | if (root == null) { 14 | return null; 15 | } 16 | 17 | // 右节点 18 | this.convertBST(root.right); 19 | 20 | // 当前节点 21 | root.val += sum; 22 | sum += root.val - sum; 23 | 24 | // 左节点 25 | this.convertBST(root.left); 26 | 27 | return root; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0540/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0540; 2 | 3 | public class Solution02 { 4 | 5 | public int singleNonDuplicate(int[] nums) { 6 | // 只有一个元素 7 | if (nums.length == 1) { 8 | return nums[0]; 9 | } 10 | 11 | int left = 0, right = nums.length - 1; 12 | while (left <= right) { 13 | int mid = left + ((right - left) >> 1); 14 | if ((mid & 1) == 1) { // 保证 mid 是偶数 15 | mid--; 16 | } 17 | // 判断 18 | if (mid != nums.length - 1 && nums[mid] == nums[mid + 1]) { 19 | left = mid + 2; // 跳两格,因为凑对了 20 | } else { 21 | right = mid - 2; // 跳两格,因为凑对了 22 | } 23 | } 24 | 25 | return nums[left]; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Solution02 solution = new Solution02(); 30 | // System.out.println(solution.singleNonDuplicate(new int[]{1, 1, 2, 3, 3, 4, 4, 8, 8})); 31 | // System.out.println(solution.singleNonDuplicate(new int[]{3, 3, 7, 7, 10, 11, 11})); 32 | System.out.println(solution.singleNonDuplicate(new int[]{1, 1, 2})); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0542/Solution04.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0542; 2 | 3 | /** 4 | * TODO 动态规划 5 | * 6 | * 参考评论区 https://leetcode-cn.com/problems/01-matrix/comments/ 的 Angus-Liu 的解答 7 | */ 8 | public class Solution04 { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0556/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0556; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/sum-of-left-leaves/ 7 | */ 8 | public class Solution { 9 | 10 | public int sumOfLeftLeaves(TreeNode root) { 11 | if (root == null) { 12 | return 0; 13 | } 14 | // 添加左节点 15 | int sum = 0; 16 | if (root.left != null) { 17 | if (root.left.right == null && root.left.left == null) { 18 | sum += root.left.val; 19 | } 20 | } 21 | 22 | return sum 23 | + this.sumOfLeftLeaves(root.left) 24 | + this.sumOfLeftLeaves(root.right); 25 | } 26 | 27 | private void doSum(TreeNode node) { 28 | if (node == null) { 29 | return; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0557/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0557; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/ 5 | * 6 | * 字符串 7 | */ 8 | public class Solution { 9 | 10 | public String reverseWords(String s) { 11 | char[] array = s.toCharArray(); 12 | // 遍历 13 | int start = 0; 14 | for (int i = 0; i <= array.length; i++) { 15 | if (i == array.length || array[i] == ' ') { 16 | swap(array, start, i - 1); 17 | start = i + 1; 18 | } 19 | } 20 | return new String(array); 21 | } 22 | 23 | private void swap(char[] array, int start, int end) { 24 | while (start < end) { 25 | // 交换 26 | char tmp = array[start]; 27 | array[start] = array[end]; 28 | array[end] = tmp; 29 | // 修改 30 | start++; 31 | end--; 32 | } 33 | } 34 | 35 | public static void main(String[] args) { 36 | Solution solution = new Solution(); 37 | System.out.println(solution.reverseWords("Let's take LeetCode contest")); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0565/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0565; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/array-nesting/ 5 | */ 6 | public class Solution { 7 | 8 | public int arrayNesting(int[] nums) { 9 | int max = 0; 10 | // 顺序遍历,并将已经遍历过的节点为 -1 ,避免重复遍历。 11 | // 关键点:能够顺序的原因是,嵌套数组,必然形成一个环。从任一一个节点进入,整个环的大小是一致的。 12 | for (int i = 0; i < nums.length; i++) { 13 | // 跳过,如果已经访问 14 | if (nums[i] == -1) { 15 | continue; 16 | } 17 | int counts = 0; 18 | // 从当前节点开始,不断遍历 19 | for (int j = i; nums[j] != -1;) { 20 | counts++; 21 | int tmp = nums[j]; 22 | nums[j] = -1; 23 | j = tmp; 24 | } 25 | // 计算最大 26 | max = Math.max(max, counts); 27 | } 28 | return max; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution solution = new Solution(); 33 | System.out.println(solution.arrayNesting(new int[]{5, 4, 0, 3, 1, 6, 2})); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0566/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0566; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/reshape-the-matrix/ 5 | */ 6 | public class Solution { 7 | 8 | public int[][] matrixReshape(int[][] nums, int r, int c) { 9 | // 校验矩阵 10 | int n = nums.length; 11 | if (n == 0) { 12 | return nums; 13 | } 14 | int m = nums[0].length; 15 | if (m == 0) { 16 | return nums; 17 | } 18 | if (n * m != r * c) { 19 | return nums; 20 | } 21 | 22 | int[][] reshape = new int[r][c]; 23 | int p = 0, q = 0; 24 | for (int i = 0; i < n; i++) { 25 | for (int j = 0; j < m; j++) { 26 | reshape[p][q] = nums[i][j]; 27 | // 设置 p、q 28 | q++; 29 | if (q == c) { 30 | p++; 31 | q = 0; 32 | } 33 | } 34 | } 35 | 36 | return reshape; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0589/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0589; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.Node; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/ 10 | * 11 | * 递归 12 | */ 13 | public class Solution { 14 | 15 | private List results = new ArrayList<>(); 16 | 17 | public List preorder(Node root) { 18 | this.traversal(root); 19 | 20 | return results; 21 | } 22 | 23 | private void traversal(Node node) { 24 | if (node == null) { 25 | return; 26 | } 27 | 28 | // 当前节点 29 | results.add(node.val); 30 | 31 | // 子节点 32 | if (node.children != null) { 33 | for (Node child : node.children) { 34 | this.traversal(child); 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0589/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0589; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.Node; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Stack; 9 | 10 | /** 11 | * 迭代 12 | */ 13 | public class Solution02 { 14 | 15 | public List preorder(Node root) { 16 | if (root == null) { 17 | return Collections.emptyList(); 18 | } 19 | 20 | List results = new ArrayList<>(); 21 | Stack stack = new Stack<>(); 22 | stack.add(root); 23 | while (!stack.isEmpty()) { 24 | // 添加到 results 中 25 | Node node = stack.pop(); 26 | results.add(node.val); 27 | // 倒序添加到 stack 中 28 | if (node.children != null) { 29 | for (int i = node.children.size() - 1; i >= 0; i--) { 30 | stack.push(node.children.get(i)); 31 | 32 | } 33 | } 34 | } 35 | 36 | return results; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0590/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0590; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.Node; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Stack; 9 | 10 | /** 11 | * https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal/ 12 | * 13 | * 迭代 14 | */ 15 | public class Solution { 16 | 17 | public List postorder(Node root) { 18 | if (root == null) { 19 | return Collections.emptyList(); 20 | } 21 | 22 | List results = new ArrayList<>(); 23 | Stack stack = new Stack<>(); 24 | stack.add(root); 25 | while (!stack.isEmpty()) { 26 | // 当前节点 27 | Node node = stack.pop(); 28 | results.add(node.val); 29 | 30 | // 子节点 31 | if (node.children != null) { 32 | stack.addAll(node.children); 33 | } 34 | } 35 | 36 | Collections.reverse(results); 37 | return results; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0594/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0594; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/longest-harmonious-subsequence/ 9 | */ 10 | public class Solution { 11 | 12 | public int findLHS(int[] nums) { 13 | // 计数 14 | Map counts = new HashMap<>(); 15 | Arrays.stream(nums).forEach(num -> counts.put(num, counts.getOrDefault(num, 0) + 1)); 16 | 17 | // 计算 18 | int max = 0; 19 | for (Map.Entry entry : counts.entrySet()) { 20 | if (!counts.containsKey(entry.getKey() + 1)) { 21 | continue; 22 | } 23 | max = Math.max(max, entry.getValue() + counts.getOrDefault(entry.getKey() + 1, 0)); 24 | } 25 | return max; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0617/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0617; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/merge-two-binary-trees/ 7 | */ 8 | public class Solution { 9 | 10 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { 11 | // 如果 t1 为空,则返回 t2 12 | if (t1 == null) { 13 | return t2; 14 | } 15 | 16 | // 合并节点 17 | if (t2 != null) { 18 | t1.val += t2.val; 19 | t1.left = this.mergeTrees(t1.left, t2.left); 20 | t1.right = this.mergeTrees(t1.right, t2.right); 21 | } 22 | 23 | return t1; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0633/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0633; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/sum-of-square-numbers/ 5 | */ 6 | public class Solution { 7 | 8 | public boolean judgeSquareSum(int c) { 9 | int left = 0; 10 | int right = (int) Math.sqrt(c); 11 | while (left <= right) { 12 | int sum = left * left + right * right; 13 | if (sum == c) { 14 | return true; 15 | } 16 | if (sum > c) { 17 | right--; 18 | } else { 19 | left++; 20 | } 21 | } 22 | 23 | return false; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution solution = new Solution(); 28 | System.out.println(solution.judgeSquareSum(5)); 29 | System.out.println(solution.judgeSquareSum(3)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0653/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0653; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/ 10 | * 11 | * 哈希表 12 | */ 13 | public class Solution { 14 | 15 | private Set numbers = new HashSet<>(); 16 | 17 | public boolean findTarget(TreeNode root, int k) { 18 | if (root == null) { 19 | return false; 20 | } 21 | 22 | // 左节点 23 | if (this.findTarget(root.left, k)) { 24 | return true; 25 | } 26 | 27 | // 当前节点 28 | if (numbers.contains(k - root.val)) { 29 | return true; 30 | } 31 | numbers.add(root.val); 32 | 33 | // 右节点 34 | return this.findTarget(root.right, k); 35 | } 36 | 37 | public static void main(String[] args) { 38 | Solution solution = new Solution(); 39 | TreeNode node = TreeNode.create(2,0,3,-4,1); 40 | System.out.println(solution.findTarget(node, -1)); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0653/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0653; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 生成有序数组 + 双指针 10 | */ 11 | public class Solution03 { 12 | 13 | public boolean findTarget(TreeNode root, int k) { 14 | // 创建数组 15 | List numbers = new ArrayList<>(); 16 | this.dfs(root, numbers); 17 | 18 | // 寻找 19 | int i = 0, j = numbers.size() - 1; 20 | while (i < j) { 21 | int sum = numbers.get(i) + numbers.get(j); 22 | if (sum == k) { 23 | return true; 24 | } 25 | if (sum > k) { 26 | j--; 27 | } else { 28 | i++; 29 | } 30 | } 31 | 32 | return false; 33 | } 34 | 35 | private void dfs(TreeNode node, List numbers) { 36 | if (node == null) { 37 | return; 38 | } 39 | this.dfs(node.left, numbers); 40 | numbers.add(node.val); 41 | this.dfs(node.right, numbers); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0667/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0667; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/beautiful-arrangement-ii/ 5 | * 6 | * 解决方案:找规律 7 | * 8 | * 参考博客:https://leetcode-cn.com/problems/beautiful-arrangement-ii/solution/leetcode-you-mei-de-pai-lie-iizhao-gui-lu-by-he-st/ 9 | */ 10 | public class Solution { 11 | 12 | public int[] constructArray(int n, int k) { 13 | int[] results = new int[n]; 14 | 15 | // 偶数,前 k 个,按照 [1, 2, 3 ..] 递增 16 | for (int i = 0, temp = 1; i <= k; i += 2) { 17 | results[i] = temp; 18 | temp++; 19 | } 20 | 21 | // 奇数,前 k 个,按照 [k + 1, k, ...] 递减 22 | // 这样,从位置 0 到 k 时,一共有 k 个间隔,想减的结果刚好是 [k, k-1, k-2, ..., 1] 递减 23 | for (int i = 1, temp = k + 1; i <= k; i += 2) { 24 | results[i] = temp; 25 | temp--; 26 | } 27 | 28 | // 从 k + 1 位置开始,顺序补位 29 | // 首个元素是,i + 1 = k + 1 + 1 = k + 2 ,避免了和第一个奇数的 k + 1 冲突. 30 | for (int i = k + 1; i < n; i++) { 31 | results[i] = i + 1; 32 | } 33 | 34 | return results; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0669/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0669; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/trim-a-binary-search-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public TreeNode trimBST(TreeNode root, int L, int R) { 11 | if (root == null) { 12 | return null; 13 | } 14 | // 满足条件,则过滤左右子树 15 | if (root.val <= R 16 | && root.val >= L) { 17 | root.left = this.trimBST(root.left, L, R); 18 | root.right = this.trimBST(root.right, L, R); 19 | return root; 20 | } 21 | // 节点大于最大值,则返回左子树,进一步缩小。 22 | if (root.val > R) { 23 | return this.trimBST(root.left, L, R); 24 | } 25 | // 节点大于最大值,则返回右子树,进一步扩大。 26 | return this.trimBST(root.right, L, R); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0671/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0671; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/second-minimum-node-in-a-binary-tree/ 7 | * 8 | * 递归 9 | * 10 | * 不等于根节点的最小值,即第二大的值。 11 | */ 12 | public class Solution { 13 | 14 | public int findSecondMinimumValue(TreeNode root) { 15 | if (root == null) { 16 | return -1; 17 | } 18 | if (root.left == null || root.right == null) { // 其实只要判断单边 19 | return -1; 20 | } 21 | 22 | // 寻找左右不等于根节点的最小值 23 | int leftValue = root.left.val == root.val ? this.findSecondMinimumValue(root.left) 24 | : root.left.val; 25 | int rightValue = root.right.val == root.val ? this.findSecondMinimumValue(root.right) 26 | : root.right.val; 27 | 28 | // 返回结果 29 | if (leftValue != -1 && rightValue != -1) { 30 | return Math.min(leftValue, rightValue); 31 | } 32 | return Math.max(leftValue, rightValue); // 有一个为 -1 ,所以可以直接求大 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0675/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0675; 2 | 3 | /** 4 | * TODO 芋艿 5 | * 6 | * 本题还有两种解法,参考 https://leetcode-cn.com/problems/cut-off-trees-for-golf-event/solution/wei-gao-er-fu-bi-sai-kan-shu-by-leetcode/ 7 | * A* 算法,和 Hadlock 算法 。 8 | */ 9 | public class Solution02 { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0685/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0685; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/redundant-connection-ii/ 5 | * 6 | * TODO 并查集,后面来做 7 | */ 8 | public class Solution { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0687/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0687; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 写的时候,略微有点卡壳了。 7 | */ 8 | public class Solution02 { 9 | 10 | private int max = 0; 11 | 12 | public int longestUnivaluePath(TreeNode root) { 13 | this.doLongestUnivaluePath0(root); 14 | 15 | return max; 16 | } 17 | 18 | private int doLongestUnivaluePath0(TreeNode root) { 19 | if (root == null) { 20 | return 0; 21 | } 22 | 23 | // 左节点的相同的编号的最大值 24 | int left = this.doLongestUnivaluePath0(root.left); 25 | // 右节点 + 同上 26 | int right = this.doLongestUnivaluePath0(root.right); 27 | 28 | // 如果当前节点和子节点相等,则使用 left + 1 ,否则只有 0 29 | left = root.left != null && root.left.val == root.val ? left + 1 : 0; 30 | // 右节点 + 同上 31 | right = root.right != null && root.right.val == root.val ? right + 1 : 0; 32 | 33 | // 求最大值 34 | max = Math.max(max, left + right); 35 | 36 | // 返回当前节点到达左子树,或者右子树,的最大值 37 | return Math.max(left, right); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0693/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0693; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/binary-number-with-alternating-bits/ 5 | * 6 | * 位操作 7 | * 8 | * ^ 异或操作 9 | */ 10 | public class Solution { 11 | 12 | public boolean hasAlternatingBits(int n) { 13 | // n 去掉最低位(最右) ,然后异或操作。 14 | int result = n ^ (n >> 1); 15 | // 如果满足条件,位就是 1111 的这样形式。这样,我们 result & (result + 1) == 0 ,相当于二进制 16 | return (result & (result + 1)) == 0; 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution solution = new Solution(); 21 | System.out.println(solution.hasAlternatingBits(4)); 22 | System.out.println(solution.hasAlternatingBits(7)); 23 | System.out.println(solution.hasAlternatingBits(5)); // true 24 | System.out.println(solution.hasAlternatingBits(11)); 25 | System.out.println(solution.hasAlternatingBits(10)); // true 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0696/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0696; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/count-binary-substrings/ 5 | */ 6 | public class Solution { 7 | 8 | public int countBinarySubstrings(String s) { 9 | int cnt = 0; 10 | 11 | int lastCounts = 0; 12 | int index = 0; 13 | while (index < s.length()) { 14 | // 计算从当前位置开始,有多少数量 15 | int counts = this.count(s, index); 16 | // 计算增加的组合。通过计算每一个数字的连续数量,对比之前另外一个数字的连续数量,取小的,就是可以增加的数。 17 | // 例如说,00110011 ,就是 2-2-2-2 ,那么可以增加的组合就是 2 + 2 + 2 = 6 . 18 | cnt += Math.min(counts, lastCounts); 19 | // 重置 last 数量 20 | lastCounts = counts; 21 | // 修改 index 22 | index += counts; 23 | } 24 | 25 | return cnt; 26 | } 27 | 28 | private int count(String s, int start) { 29 | int startCh = s.charAt(start); 30 | int startChCounts = 0; 31 | 32 | // 计算 startCh 数量 33 | while (start < s.length() 34 | && s.charAt(start) == startCh) { 35 | startChCounts++; 36 | start++; 37 | } 38 | 39 | return startChCounts; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0700/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0700; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/search-in-a-binary-search-tree/ 7 | */ 8 | public class Solution { 9 | 10 | public TreeNode searchBST(TreeNode root, int val) { 11 | if (root == null) { 12 | return null; 13 | } 14 | if (root.val == val) { 15 | return root; 16 | } 17 | return root.val < val ? this.searchBST(root.right, val) 18 | : this.searchBST(root.left, val); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0701/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0701; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 和 {@link Solution} 一样的思路,差别在于简化代码 7 | */ 8 | public class Solution02 { 9 | 10 | public TreeNode insertIntoBST(TreeNode root, int val) { 11 | if (root == null) { 12 | return new TreeNode(val); 13 | } 14 | 15 | if (val > root.val) { 16 | root.right = this.insertIntoBST(root.right, val); 17 | } else { 18 | root.left = this.insertIntoBST(root.left, val); 19 | } 20 | 21 | return root; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0704/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0704; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/binary-search/ 5 | */ 6 | public class Solution { 7 | 8 | public int search(int[] nums, int target) { 9 | int left = 0, right = nums.length - 1; 10 | while (left <= right) { 11 | int middle = left + ((right - left) >> 1); 12 | if (nums[middle] == target) { 13 | return middle; 14 | } 15 | if (nums[middle] > target) { 16 | right = middle - 1; 17 | } else { 18 | left = left + 1; 19 | } 20 | } 21 | 22 | return -1; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0714/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0714; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/ 5 | * 6 | * 动态规划 7 | * 8 | * sell[i] = Math.max(sell[i - 1], buy[i - 1] + nums[i] - fee) 9 | * buy[i] = Math.max(buy[i - 1], sell[i - 1] - nums[i]) 10 | */ 11 | public class Solution { 12 | 13 | public int maxProfit(int[] prices, int fee) { 14 | // 初始化 15 | if (prices.length == 0) { 16 | return 0; 17 | } 18 | int sell = 0; 19 | int buy = -prices[0]; 20 | 21 | // 开始 dp 22 | for (int i = 1; i < prices.length; i++) { 23 | // 当前轮 24 | int price = prices[i]; 25 | int sellNow = Math.max(sell, buy + price - fee); 26 | int buyNow = Math.max(buy, sell - price); 27 | // 赋值 28 | sell = sellNow; 29 | buy = buyNow; 30 | } 31 | return sell; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0714/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0714; 2 | 3 | /** 4 | * 在 {@link Solution} 上优化 5 | * 6 | * 因为不限制购买次数,所以即使出售后,我们还是可以购买股票噢。 7 | */ 8 | public class Solution02 { 9 | 10 | public int maxProfit(int[] prices, int fee) { 11 | // 初始化 12 | if (prices.length == 0) { 13 | return 0; 14 | } 15 | int sell = 0; 16 | int buy = -prices[0]; 17 | 18 | // 开始 dp 19 | for (int i = 1; i < prices.length; i++) { 20 | // 当前轮 21 | int price = prices[i]; 22 | sell = Math.max(sell, buy + price - fee); 23 | buy = Math.max(buy, sell - price); 24 | } 25 | return sell; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0746/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0746; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/min-cost-climbing-stairs/ 5 | * 6 | * 动态规划 7 | * 8 | * f[2] = Math.min(f[1], f[0]) + cost[2] 9 | */ 10 | public class Solution { 11 | 12 | public int minCostClimbingStairs(int[] cost) { 13 | if (cost.length == 0) { 14 | return 0; 15 | } 16 | if (cost.length == 1) { 17 | return cost[0]; 18 | } 19 | int f0 = cost[0]; 20 | int f1 = cost[1]; 21 | for (int i = 2; i < cost.length; i++) { 22 | // 计算当前楼梯,最小值 23 | int f2 = Math.min(f0, f1) + cost[i]; 24 | // 切换值 25 | f0 = f1; 26 | f1 = f2; 27 | } 28 | return Math.min(f0, f1); 29 | } 30 | 31 | public static void main(String[] args) { 32 | Solution solution = new Solution(); 33 | System.out.println(solution.minCostClimbingStairs(new int[]{10, 15, 20})); 34 | System.out.println(solution.minCostClimbingStairs(new int[]{1, 100, 1, 1, 1, 100, 1, 1, 100, 1})); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0766/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0766; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/toeplitz-matrix/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china 5 | */ 6 | public class Solution { 7 | 8 | public boolean isToeplitzMatrix(int[][] matrix) { 9 | for (int i = 1; i < matrix.length; i++) { 10 | for (int j = 1; j < matrix[0].length; j++) { 11 | // 和左上角比较 12 | if (matrix[i][j] != matrix[i - 1][j -1]) { 13 | return false; 14 | } 15 | } 16 | } 17 | 18 | return true; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0769/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0769; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/max-chunks-to-make-sorted/ 5 | */ 6 | public class Solution { 7 | 8 | public int maxChunksToSorted(int[] arr) { 9 | int maxChunks = 0; 10 | int maxNumber = 0; 11 | for (int i = 0; i < arr.length; i++) { 12 | // 求当前的最大值 13 | maxNumber = Math.max(maxNumber, arr[i]); 14 | // 当前下标,和 maxNumber 相等,说明前 i 个,在 [0, maxNumber] 内。 15 | // 注意噢,arr 中,数字是从 0 开始的。 16 | if (maxNumber == i) { 17 | maxChunks++; 18 | } 19 | } 20 | 21 | return maxChunks; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | System.out.println(solution.maxChunksToSorted(new int[]{4, 3, 2, 1, 0})); 27 | System.out.println(solution.maxChunksToSorted(new int[]{1, 0, 2, 3, 4})); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0776/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0776; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 在 {@link Solution} 上,简单优化,不每次 new 数组 7 | */ 8 | public class Solution02 { 9 | 10 | public TreeNode[] splitBST(TreeNode root, int V) { 11 | // 节点为空的情况 12 | if (root == null) { 13 | return new TreeNode[]{null, null}; 14 | } 15 | 16 | if (V < root.val) { 17 | TreeNode[] results = this.splitBST(root.left, V); 18 | root.left = results[1]; 19 | results[1] = root; 20 | return results; 21 | } 22 | TreeNode[] results = this.splitBST(root.right, V); 23 | root.right = results[0]; 24 | results[0] = root; 25 | return results; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0784/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0784; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * https://leetcode-cn.com/problems/letter-case-permutation/ 8 | * 9 | * 回溯算法 10 | * 11 | * 写的有点傻,修改下 12 | */ 13 | public class Solution { 14 | 15 | private List results = new ArrayList<>(); 16 | 17 | public List letterCasePermutation(String S) { 18 | this.letterCasePermutation(0, S, ""); 19 | return results; 20 | } 21 | 22 | private void letterCasePermutation(int i, String s, String current) { 23 | if (i == s.length()) { 24 | results.add(current); 25 | return; 26 | } 27 | char ch = s.charAt(i); 28 | this.letterCasePermutation(i + 1, s, current + ch); 29 | // TODO 芋艿,此处可以通过位操作,来大小写转换,后续在优化。 30 | if (ch >= 'a' && ch <= 'z') { 31 | this.letterCasePermutation(i + 1, s, current + Character.toUpperCase(ch)); 32 | } else if (ch >= 'A' && ch <= 'Z') { 33 | this.letterCasePermutation(i + 1, s, current + Character.toLowerCase(ch)); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0784/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0784; 2 | 3 | public class Solution02 { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0814/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0814; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/binary-tree-pruning/ 7 | * 8 | * 通过子节点求和 9 | */ 10 | public class Solution { 11 | 12 | public TreeNode pruneTree(TreeNode root) { 13 | TreeNode dummy = new TreeNode(1); 14 | dummy.left = root; 15 | this.pruneTree0(dummy); 16 | 17 | return dummy.left; 18 | } 19 | 20 | private int pruneTree0(TreeNode node) { 21 | if (node == null) { 22 | return 0; 23 | } 24 | 25 | int leftSum = this.pruneTree0(node.left); 26 | if (leftSum == 0) { 27 | node.left = null; 28 | } 29 | int rightSum = this.pruneTree0(node.right); 30 | if (rightSum == 0) { 31 | node.right = null; 32 | } 33 | 34 | return leftSum + rightSum + node.val; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0814/Solution02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0814; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 在 {@link Solution} 上,优化递归逻辑 7 | */ 8 | public class Solution02 { 9 | 10 | public TreeNode pruneTree(TreeNode root) { 11 | if (root == null) { 12 | return null; 13 | } 14 | 15 | // 递归左右子树 16 | root.left = this.pruneTree(root.left); 17 | root.right = this.pruneTree(root.right); 18 | 19 | if (root.val == 0 && root.left == null && root.right == null) { 20 | return null; 21 | } 22 | return root; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0841/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0841; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/keys-and-rooms/ 7 | * 8 | * DFS 9 | */ 10 | public class Solution { 11 | 12 | private int n; 13 | private boolean[] visits; 14 | private List> rooms; 15 | 16 | public boolean canVisitAllRooms(List> rooms) { 17 | // 初始化 18 | this.n = rooms.size(); 19 | this.visits = new boolean[this.n]; 20 | this.rooms = rooms; 21 | 22 | // dfs 23 | this.dfs(0); 24 | return n == 0; 25 | } 26 | 27 | private void dfs(int index) { 28 | if (visits[index]) { 29 | return; 30 | } 31 | // 标记已访问 32 | visits[index] = true; 33 | this.n--; 34 | 35 | // 遍历后续节点 36 | for (int nextIndex : rooms.get(index)) { 37 | this.dfs(nextIndex); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0852/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0852; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/ 5 | * 6 | * 顺序遍历,因为题目默认就存在,先升序,后降序。 7 | * 8 | * 最粗暴的方法,时间复杂度是 O(N) 9 | */ 10 | public class Solution { 11 | 12 | public int peakIndexInMountainArray(int[] A) { 13 | assert A.length >= 3; 14 | 15 | for (int i = 0; i < A.length - 1; i++) { 16 | if (A[i] > A[i + 1]) { 17 | return i; 18 | } 19 | } 20 | 21 | throw new IllegalArgumentException("根据题目,不存在这个情况"); 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | System.out.println(solution.peakIndexInMountainArray(new int[]{0, 1, 0})); 27 | System.out.println(solution.peakIndexInMountainArray(new int[]{0, 2, 1, 0})); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0856/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0856; 2 | 3 | /** 4 | * https://leetcode-cn.com/problems/score-of-parentheses/ 5 | */ 6 | public class Solution { 7 | 8 | /** 9 | * 下标 10 | */ 11 | private int index; 12 | 13 | public int scoreOfParentheses(String S) { 14 | int number = 0; 15 | for (; index < S.length();) { 16 | if (S.charAt(index) == '(') { 17 | index++; 18 | number = number + this.scoreOfParentheses(S); 19 | } else { 20 | index++; 21 | return number > 0 ? 2 * number : 1; 22 | } 23 | } 24 | return number; 25 | } 26 | 27 | public static void main(String[] args) { 28 | // Solution solution = new Solution(); 29 | System.out.println(new Solution().scoreOfParentheses("()")); 30 | System.out.println(new Solution().scoreOfParentheses("(())")); 31 | System.out.println(new Solution().scoreOfParentheses("(()(()))")); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0872/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0872; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * https://leetcode-cn.com/problems/leaf-similar-trees/ 10 | */ 11 | public class Solution { 12 | 13 | public boolean leafSimilar(TreeNode root1, TreeNode root2) { 14 | List results1 = new ArrayList<>(); 15 | List results2 = new ArrayList<>(); 16 | // 收集叶子节点 17 | this.dfs(root1, results1); 18 | this.dfs(root2, results2); 19 | 20 | // 对比 21 | if (results1.size() != results2.size()) { 22 | return false; 23 | } 24 | for (int i = 0; i < results1.size(); i++) { 25 | if (!results1.get(i).equals(results2.get(i))) { 26 | return false; 27 | } 28 | } 29 | return true; 30 | } 31 | 32 | private void dfs(TreeNode node, List result) { 33 | if (node == null) { 34 | return; 35 | } 36 | if (node.left == null && node.right == null) { 37 | result.add(node.val); 38 | } 39 | 40 | // 左右节点 41 | this.dfs(node.left, result); 42 | this.dfs(node.right, result); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0965/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0965; 2 | 3 | import cn.iocoder.algorithm.leetcode.common.TreeNode; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/univalued-binary-tree/ 7 | * 8 | * 递归 9 | */ 10 | public class Solution { 11 | 12 | public boolean isUnivalTree(TreeNode root) { 13 | if (root == null) { 14 | return true; 15 | } 16 | 17 | return isSame(root, root.val); 18 | } 19 | 20 | private boolean isSame(TreeNode node, int val) { 21 | if (node == null) { 22 | return true; 23 | } 24 | if (node.val != val) { 25 | return false; 26 | } 27 | 28 | return this.isSame(node.left, val) 29 | && this.isSame(node.right, val); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0981/TimeMap02.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0981; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.TreeMap; 6 | 7 | /** 8 | * https://leetcode-cn.com/problems/time-based-key-value-store/ 9 | * 10 | * 使用 TreeMap 实现 11 | * 12 | * 实际结果,超时。尴尬~ 13 | */ 14 | public class TimeMap02 { 15 | 16 | // Integer 指的是 timestamp 17 | private Map> timeMap = new HashMap<>(); 18 | 19 | /** Initialize your data structure here. */ 20 | public TimeMap02() { 21 | } 22 | 23 | public void set(String key, String value, int timestamp) { 24 | Map times = timeMap.computeIfAbsent(key, s -> new TreeMap<>()); 25 | times.put(timestamp, value); 26 | } 27 | 28 | public String get(String key, int timestamp) { 29 | TreeMap times = timeMap.get(key); 30 | if (times == null) { 31 | return ""; 32 | } 33 | 34 | // 返回 timestamp 最接近的 key 。关键 35 | Integer floorKey = times.floorKey(timestamp); 36 | return floorKey != null ? times.get(floorKey) : ""; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0996/Solution03.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0996; 2 | 3 | /** 4 | * TODO 芋艿 DP 解法 https://leetcode-cn.com/problems/number-of-squareful-arrays/solution/zheng-fang-xing-shu-zu-de-shu-mu-by-leetcode/ 5 | */ 6 | public class Solution03 { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/no0997/Solution.java: -------------------------------------------------------------------------------- 1 | package cn.iocoder.algorithm.leetcode.no0997; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * https://leetcode-cn.com/problems/squares-of-a-sorted-array/ 7 | * 8 | * 最粗暴的做法,求和 + 快排 9 | * 10 | * 参考博客:https://leetcode-cn.com/problems/squares-of-a-sorted-array/solution/you-xu-shu-zu-de-ping-fang-by-leetcode/ 11 | */ 12 | public class Solution { 13 | 14 | public int[] sortedSquares(int[] A) { 15 | // 平方 16 | int[] results = new int[A.length]; 17 | for (int i = 0; i < A.length; i++) { 18 | results[i] = A[i] * A[i]; 19 | } 20 | 21 | // 排序并返回 22 | Arrays.sort(results); 23 | return results; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/iocoder/algorithm/leetcode/text: -------------------------------------------------------------------------------- 1 | 颠倒给定的 32 位无符号整数的二进制位。 2 | 3 |   4 | 5 | 示例 1: 6 | 7 | 输入: 00000010100101000001111010011100 8 | 输出: 00111001011110000010100101000000 9 | 解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596, 10 | 因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。 11 | 示例 2: 12 | 13 | 输入:11111111111111111111111111111101 14 | 输出:10111111111111111111111111111111 15 | 解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293, 16 |   因此返回 3221225471 其二进制表示形式为 10101111110010110010011101101001。 17 |   18 | 19 | 提示: 20 | 21 | 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。 22 | 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。 23 |   24 | 25 | 进阶: 26 | 如果多次调用这个函数,你将如何优化你的算法? 27 | 28 | 来源:力扣(LeetCode) 29 | 链接:https://leetcode-cn.com/problems/reverse-bits 30 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | --------------------------------------------------------------------------------