├── .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 |
--------------------------------------------------------------------------------