From a917b4460ed306905f80ce33694d80e7de0dfb0f Mon Sep 17 00:00:00 2001
From: CyC2018 <1029579233@qq.com>
Date: Fri, 22 Jun 2018 13:31:49 +0800
Subject: [PATCH] auto commit
---
notes/Leetcode 题解.md | 669 +++++++++++++++++++++--------------------
1 file changed, 335 insertions(+), 334 deletions(-)
diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md
index 44bddaa3..8019c806 100644
--- a/notes/Leetcode 题解.md
+++ b/notes/Leetcode 题解.md
@@ -15,14 +15,14 @@
* [分治](#分治)
* [动态规划](#动态规划)
* [斐波那契数列](#斐波那契数列)
+ * [矩阵路径](#矩阵路径)
+ * [数组区间](#数组区间)
+ * [分割整数](#分割整数)
* [最长递增子序列](#最长递增子序列)
* [最长公共子序列](#最长公共子序列)
* [0-1 背包](#0-1-背包)
- * [数组区间](#数组区间)
+ * [股票交易](#股票交易)
* [字符串编辑](#字符串编辑)
- * [分割整数](#分割整数)
- * [矩阵路径](#矩阵路径)
- * [其它问题](#其它问题)
* [数学](#数学)
* [素数](#素数)
* [最大公约数](#最大公约数)
@@ -2477,6 +2477,258 @@ private int rob(int[] nums, int first, int last) {
dp[N] 即为所求。
+### 矩阵路径
+
+**矩阵的最小路径和**
+
+[64. Minimum Path Sum (Medium)](https://leetcode.com/problems/minimum-path-sum/description/)
+
+```html
+[[1,3,1],
+ [1,5,1],
+ [4,2,1]]
+Given the above grid map, return 7. Because the path 1→3→1→1→1 minimizes the sum.
+```
+
+题目描述:求从矩阵的左上角到右下角的最小路径和,每次只能向右和向下移动。
+
+```java
+public int minPathSum(int[][] grid) {
+ if (grid.length == 0 || grid[0].length == 0) {
+ return 0;
+ }
+ int m = grid.length, n = grid[0].length;
+ int[] dp = new int[n];
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ if (j == 0) {
+ dp[j] = dp[j]; // 只能从上侧走到该位置
+ } else if (i == 0) {
+ dp[j] = dp[j - 1]; // 只能从左侧走到该位置
+ } else {
+ dp[j] = Math.min(dp[j - 1], dp[j]);
+ }
+ dp[j] += grid[i][j];
+ }
+ }
+ return dp[n - 1];
+}
+```
+
+**矩阵的总路径数**
+
+[62. Unique Paths (Medium)](https://leetcode.com/problems/unique-paths/description/)
+
+题目描述:统计从矩阵左上角到右下角的路径总数,每次只能向右或者向下移动。
+
+
+
+```java
+public int uniquePaths(int m, int n) {
+ int[] dp = new int[n];
+ Arrays.fill(dp, 1);
+ for (int i = 1; i < m; i++) {
+ for (int j = 1; j < n; j++) {
+ dp[j] = dp[j] + dp[j - 1];
+ }
+ }
+ return dp[n - 1];
+}
+```
+
+也可以直接用数学公式求解,这是一个组合问题。机器人总共移动的次数 S=m+n-2,向下移动的次数 D=m-1,那么问题可以看成从 S 从取出 D 个位置的组合数量,这个问题的解为 C(S, D)。
+
+```java
+public int uniquePaths(int m, int n) {
+ int S = m + n - 2; // 总共的移动次数
+ int D = m - 1; // 向下的移动次数
+ long ret = 1;
+ for (int i = 1; i <= D; i++) {
+ ret = ret * (S - D + i) / i;
+ }
+ return (int) ret;
+}
+```
+
+### 数组区间
+
+**数组区间和**
+
+[303. Range Sum Query - Immutable (Easy)](https://leetcode.com/problems/range-sum-query-immutable/description/)
+
+```html
+Given nums = [-2, 0, 3, -5, 2, -1]
+
+sumRange(0, 2) -> 1
+sumRange(2, 5) -> -1
+sumRange(0, 5) -> -3
+```
+
+求区间 i \~ j 的和,可以转换为 sum[j] - sum[i-1],其中 sum[i] 为 0 \~ i 的和。
+
+```java
+class NumArray {
+ private int[] sums;
+
+ public NumArray(int[] nums) {
+ sums = new int[nums.length];
+ for (int i = 0; i < nums.length; i++) {
+ sums[i] = i == 0 ? nums[0] : sums[i - 1] + nums[i];
+ }
+ }
+
+ public int sumRange(int i, int j) {
+ return i == 0 ? sums[j] : sums[j] - sums[i - 1];
+ }
+}
+```
+
+**子数组最大的和**
+
+[53. Maximum Subarray (Easy)](https://leetcode.com/problems/maximum-subarray/description/)
+
+```html
+For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
+the contiguous subarray [4,-1,2,1] has the largest sum = 6.
+```
+
+```java
+public int maxSubArray(int[] nums) {
+ if (nums == null || nums.length == 0) {
+ return 0;
+ }
+ int preSum = nums[0];
+ int maxSum = preSum;
+ for (int i = 1; i < nums.length; i++) {
+ preSum = preSum > 0 ? preSum + nums[i] : nums[i];
+ maxSum = Math.max(maxSum, preSum);
+ }
+ return maxSum;
+}
+```
+
+**数组中等差递增子区间的个数**
+
+[413. Arithmetic Slices (Medium)](https://leetcode.com/problems/arithmetic-slices/description/)
+
+```html
+A = [1, 2, 3, 4]
+return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
+```
+
+dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。
+
+如果 A[i] - A[i - 1] == A[i - 1] - A[i - 2],表示 [A[i - 2], A[i - 1], A[i]] 是一个等差递增子区间。如果 [A[i - 3], A[i - 2], A[i - 1]] 是一个等差递增子区间,那么 [A[i - 3], A[i - 2], A[i - 1], A[i]] 也是。因此在这个条件下,dp[i] = dp[i-1] + 1。
+
+```java
+public int numberOfArithmeticSlices(int[] A) {
+ if (A == null || A.length == 0) {
+ return 0;
+ }
+ int n = A.length;
+ int[] dp = new int[n];
+ for (int i = 2; i < n; i++) {
+ if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
+ dp[i] = dp[i - 1] + 1;
+ }
+ }
+ int total = 0;
+ for (int cnt : dp) {
+ total += cnt;
+ }
+ return total;
+}
+```
+
+### 分割整数
+
+**分割整数的最大乘积**
+
+[343. Integer Break (Medim)](https://leetcode.com/problems/integer-break/description/)
+
+题目描述:For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
+
+```java
+public int integerBreak(int n) {
+ int[] dp = new int[n + 1];
+ dp[1] = 1;
+ for (int i = 2; i <= n; i++) {
+ for (int j = 1; j <= i - 1; j++) {
+ dp[i] = Math.max(dp[i], Math.max(j * dp[i - j], j * (i - j)));
+ }
+ }
+ return dp[n];
+}
+```
+
+**按平方数来分割整数**
+
+[279. Perfect Squares(Medium)](https://leetcode.com/problems/perfect-squares/description/)
+
+题目描述:For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
+
+```java
+public int numSquares(int n) {
+ List squareList = generateSquareList(n);
+ int[] dp = new int[n + 1];
+ for (int i = 1; i <= n; i++) {
+ int min = Integer.MAX_VALUE;
+ for (int square : squareList) {
+ if (square > i) {
+ break;
+ }
+ min = Math.min(min, dp[i - square] + 1);
+ }
+ dp[i] = min;
+ }
+ return dp[n];
+}
+
+private List generateSquareList(int n) {
+ List squareList = new ArrayList<>();
+ int diff = 3;
+ int square = 1;
+ while (square <= n) {
+ squareList.add(square);
+ square += diff;
+ diff += 2;
+ }
+ return squareList;
+}
+```
+
+**分割整数构成字母字符串**
+
+[91. Decode Ways (Medium)](https://leetcode.com/problems/decode-ways/description/)
+
+题目描述:Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
+
+```java
+public int numDecodings(String s) {
+ if (s == null || s.length() == 0) {
+ return 0;
+ }
+ int n = s.length();
+ int[] dp = new int[n + 1];
+ dp[0] = 1;
+ dp[1] = s.charAt(0) == '0' ? 0 : 1;
+ for (int i = 2; i <= n; i++) {
+ int one = Integer.valueOf(s.substring(i - 1, i));
+ if (one != 0) {
+ dp[i] += dp[i - 1];
+ }
+ if (s.charAt(i - 2) == '0') {
+ continue;
+ }
+ int two = Integer.valueOf(s.substring(i - 2, i));
+ if (two <= 26) {
+ dp[i] += dp[i - 2];
+ }
+ }
+ return dp[n];
+}
+```
+
### 最长递增子序列
已知一个序列 {S1, S2,...,Sn} ,取出若干数组成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个 **子序列** 。
@@ -3072,93 +3324,95 @@ public int maxProfit(int[] prices) {
}
```
-### 数组区间
+### 股票交易
-**数组区间和**
+**需要冷却期的股票交易**
-[303. Range Sum Query - Immutable (Easy)](https://leetcode.com/problems/range-sum-query-immutable/description/)
+[309. Best Time to Buy and Sell Stock with Cooldown(Medium)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/)
-```html
-Given nums = [-2, 0, 3, -5, 2, -1]
+题目描述:交易之后需要有一天的冷却时间。
-sumRange(0, 2) -> 1
-sumRange(2, 5) -> -1
-sumRange(0, 5) -> -3
-```
-
-求区间 i \~ j 的和,可以转换为 sum[j] - sum[i-1],其中 sum[i] 为 0 \~ i 的和。
+
```java
-class NumArray {
- private int[] sums;
-
- public NumArray(int[] nums) {
- sums = new int[nums.length];
- for (int i = 0; i < nums.length; i++) {
- sums[i] = i == 0 ? nums[0] : sums[i - 1] + nums[i];
- }
+public int maxProfit(int[] prices) {
+ if (prices == null || prices.length == 0) {
+ return 0;
}
-
- public int sumRange(int i, int j) {
- return i == 0 ? sums[j] : sums[j] - sums[i - 1];
+ int N = prices.length;
+ int[] buy = new int[N];
+ int[] s1 = new int[N];
+ int[] sell = new int[N];
+ int[] s2 = new int[N];
+ s1[0] = buy[0] = -prices[0];
+ sell[0] = s2[0] = 0;
+ for (int i = 1; i < N; i++) {
+ buy[i] = s2[i - 1] - prices[i];
+ s1[i] = Math.max(buy[i - 1], s1[i - 1]);
+ sell[i] = Math.max(buy[i - 1], s1[i - 1]) + prices[i];
+ s2[i] = Math.max(s2[i - 1], sell[i - 1]);
}
+ return Math.max(sell[N - 1], s2[N - 1]);
}
```
-**子数组最大的和**
+**需要交易费用的股票交易**
-[53. Maximum Subarray (Easy)](https://leetcode.com/problems/maximum-subarray/description/)
+[714. Best Time to Buy and Sell Stock with Transaction Fee (Medium)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/)
```html
-For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
-the contiguous subarray [4,-1,2,1] has the largest sum = 6.
+Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
+Output: 8
+Explanation: The maximum profit can be achieved by:
+Buying at prices[0] = 1
+Selling at prices[3] = 8
+Buying at prices[4] = 4
+Selling at prices[5] = 9
+The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
```
+题目描述:每交易一次,都要支付一定的费用。
+
+
+
```java
-public int maxSubArray(int[] nums) {
- if (nums == null || nums.length == 0) {
- return 0;
+public int maxProfit(int[] prices, int fee) {
+ int N = prices.length;
+ int[] buy = new int[N];
+ int[] s1 = new int[N];
+ int[] sell = new int[N];
+ int[] s2 = new int[N];
+ s1[0] = buy[0] = -prices[0];
+ sell[0] = s2[0] = 0;
+ for (int i = 1; i < N; i++) {
+ buy[i] = Math.max(sell[i - 1], s2[i - 1]) - prices[i];
+ s1[i] = Math.max(buy[i - 1], s1[i - 1]);
+ sell[i] = Math.max(buy[i - 1], s1[i - 1]) - fee + prices[i];
+ s2[i] = Math.max(s2[i - 1], sell[i - 1]);
}
- int preSum = nums[0];
- int maxSum = preSum;
- for (int i = 1; i < nums.length; i++) {
- preSum = preSum > 0 ? preSum + nums[i] : nums[i];
- maxSum = Math.max(maxSum, preSum);
- }
- return maxSum;
+ return Math.max(sell[N - 1], s2[N - 1]);
}
```
-**数组中等差递增子区间的个数**
+**买入和售出股票最大的收益**
-[413. Arithmetic Slices (Medium)](https://leetcode.com/problems/arithmetic-slices/description/)
+[121. Best Time to Buy and Sell Stock (Easy)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/)
-```html
-A = [1, 2, 3, 4]
-return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
-```
+题目描述:只进行一次交易。
-dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。
-
-如果 A[i] - A[i - 1] == A[i - 1] - A[i - 2],表示 [A[i - 2], A[i - 1], A[i]] 是一个等差递增子区间。如果 [A[i - 3], A[i - 2], A[i - 1]] 是一个等差递增子区间,那么 [A[i - 3], A[i - 2], A[i - 1], A[i]] 也是。因此在这个条件下,dp[i] = dp[i-1] + 1。
+只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。
```java
-public int numberOfArithmeticSlices(int[] A) {
- if (A == null || A.length == 0) {
- return 0;
+public int maxProfit(int[] prices) {
+ int n = prices.length;
+ if (n == 0) return 0;
+ int soFarMin = prices[0];
+ int max = 0;
+ for (int i = 1; i < n; i++) {
+ if (soFarMin > prices[i]) soFarMin = prices[i];
+ else max = Math.max(max, prices[i] - soFarMin);
}
- int n = A.length;
- int[] dp = new int[n];
- for (int i = 2; i < n; i++) {
- if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
- dp[i] = dp[i - 1] + 1;
- }
- }
- int total = 0;
- for (int cnt : dp) {
- total += cnt;
- }
- return total;
+ return max;
}
```
@@ -3249,257 +3503,6 @@ public int minDistance(String word1, String word2) {
}
```
-### 分割整数
-
-**分割整数的最大乘积**
-
-[343. Integer Break (Medim)](https://leetcode.com/problems/integer-break/description/)
-
-题目描述:For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
-
-```java
-public int integerBreak(int n) {
- int[] dp = new int[n + 1];
- dp[1] = 1;
- for (int i = 2; i <= n; i++) {
- for (int j = 1; j <= i - 1; j++) {
- dp[i] = Math.max(dp[i], Math.max(j * dp[i - j], j * (i - j)));
- }
- }
- return dp[n];
-}
-```
-
-**按平方数来分割整数**
-
-[279. Perfect Squares(Medium)](https://leetcode.com/problems/perfect-squares/description/)
-
-题目描述:For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
-
-```java
-public int numSquares(int n) {
- List squareList = generateSquareList(n);
- int[] dp = new int[n + 1];
- for (int i = 1; i <= n; i++) {
- int min = Integer.MAX_VALUE;
- for (int square : squareList) {
- if (square > i) {
- break;
- }
- min = Math.min(min, dp[i - square] + 1);
- }
- dp[i] = min;
- }
- return dp[n];
-}
-
-private List generateSquareList(int n) {
- List squareList = new ArrayList<>();
- int diff = 3;
- int square = 1;
- while (square <= n) {
- squareList.add(square);
- square += diff;
- diff += 2;
- }
- return squareList;
-}
-```
-
-**分割整数构成字母字符串**
-
-[91. Decode Ways (Medium)](https://leetcode.com/problems/decode-ways/description/)
-
-题目描述:Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
-
-```java
-public int numDecodings(String s) {
- if (s == null || s.length() == 0) {
- return 0;
- }
- int n = s.length();
- int[] dp = new int[n + 1];
- dp[0] = 1;
- dp[1] = s.charAt(0) == '0' ? 0 : 1;
- for (int i = 2; i <= n; i++) {
- int one = Integer.valueOf(s.substring(i - 1, i));
- if (one != 0) {
- dp[i] += dp[i - 1];
- }
- if (s.charAt(i - 2) == '0') {
- continue;
- }
- int two = Integer.valueOf(s.substring(i - 2, i));
- if (two <= 26) {
- dp[i] += dp[i - 2];
- }
- }
- return dp[n];
-}
-```
-
-### 矩阵路径
-
-**矩阵的总路径数**
-
-[62. Unique Paths (Medium)](https://leetcode.com/problems/unique-paths/description/)
-
-题目描述:统计从矩阵左上角到右下角的路径总数,每次只能向右或者向下移动。
-
-
-
-```java
-public int uniquePaths(int m, int n) {
- int[] dp = new int[n];
- Arrays.fill(dp, 1);
- for (int i = 1; i < m; i++) {
- for (int j = 1; j < n; j++) {
- dp[j] = dp[j] + dp[j - 1];
- }
- }
- return dp[n - 1];
-}
-```
-
-也可以直接用数学公式求解,这是一个组合问题。机器人总共移动的次数 S=m+n-2,向下移动的次数 D=m-1,那么问题可以看成从 S 从取出 D 个位置的组合数量,这个问题的解为 C(S, D)。
-
-```java
-public int uniquePaths(int m, int n) {
- int S = m + n - 2; // 总共的移动次数
- int D = m - 1; // 向下的移动次数
- long ret = 1;
- for (int i = 1; i <= D; i++) {
- ret = ret * (S - D + i) / i;
- }
- return (int) ret;
-}
-```
-
-**矩阵的最小路径和**
-
-[64. Minimum Path Sum (Medium)](https://leetcode.com/problems/minimum-path-sum/description/)
-
-```html
-[[1,3,1],
- [1,5,1],
- [4,2,1]]
-Given the above grid map, return 7. Because the path 1→3→1→1→1 minimizes the sum.
-```
-
-题目描述:求从矩阵的左上角到右下角的最小路径和,每次只能向左和向下移动。
-
-```java
-public int minPathSum(int[][] grid) {
- if (grid.length == 0 || grid[0].length == 0) {
- return 0;
- }
- int m = grid.length, n = grid[0].length;
- int[] dp = new int[n];
- for (int i = 0; i < m; i++) {
- for (int j = 0; j < n; j++) {
- if (j == 0) {
- dp[0] = dp[0] + grid[i][0]; // 只能从上侧走到该位置
- } else if (i == 0) {
- dp[j] = dp[j - 1] + grid[0][j]; // 只能从右侧走到该位置
- } else {
- dp[j] = Math.min(dp[j - 1], dp[j]) + grid[i][j];
- }
- }
- }
- return dp[n - 1];
-}
-```
-
-### 其它问题
-
-**需要冷却期的股票交易**
-
-[309. Best Time to Buy and Sell Stock with Cooldown(Medium)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/)
-
-题目描述:交易之后需要有一天的冷却时间。
-
-
-
-```java
-public int maxProfit(int[] prices) {
- if (prices == null || prices.length == 0) return 0;
- int N = prices.length;
- int[] buy = new int[N];
- int[] s1 = new int[N];
- int[] sell = new int[N];
- int[] s2 = new int[N];
- s1[0] = buy[0] = -prices[0];
- sell[0] = s2[0] = 0;
- for (int i = 1; i < N; i++) {
- buy[i] = s2[i - 1] - prices[i];
- s1[i] = Math.max(buy[i - 1], s1[i - 1]);
- sell[i] = Math.max(buy[i - 1], s1[i - 1]) + prices[i];
- s2[i] = Math.max(s2[i - 1], sell[i - 1]);
- }
- return Math.max(sell[N - 1], s2[N - 1]);
-}
-```
-
-**需要交易费用的股票交易**
-
-[714. Best Time to Buy and Sell Stock with Transaction Fee (Medium)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/)
-
-```html
-Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
-Output: 8
-Explanation: The maximum profit can be achieved by:
-Buying at prices[0] = 1
-Selling at prices[3] = 8
-Buying at prices[4] = 4
-Selling at prices[5] = 9
-The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
-```
-
-题目描述:每交易一次,都要支付一定的费用。
-
-
-
-```java
-public int maxProfit(int[] prices, int fee) {
- int N = prices.length;
- int[] buy = new int[N];
- int[] s1 = new int[N];
- int[] sell = new int[N];
- int[] s2 = new int[N];
- s1[0] = buy[0] = -prices[0];
- sell[0] = s2[0] = 0;
- for (int i = 1; i < N; i++) {
- buy[i] = Math.max(sell[i - 1], s2[i - 1]) - prices[i];
- s1[i] = Math.max(buy[i - 1], s1[i - 1]);
- sell[i] = Math.max(buy[i - 1], s1[i - 1]) - fee + prices[i];
- s2[i] = Math.max(s2[i - 1], sell[i - 1]);
- }
- return Math.max(sell[N - 1], s2[N - 1]);
-}
-```
-
-**买入和售出股票最大的收益**
-
-[121. Best Time to Buy and Sell Stock (Easy)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/)
-
-只进行一次交易。
-
-只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。
-
-```java
-public int maxProfit(int[] prices) {
- int n = prices.length;
- if(n == 0) return 0;
- int soFarMin = prices[0];
- int max = 0;
- for(int i = 1; i < n; i++){
- if(soFarMin > prices[i]) soFarMin = prices[i];
- else max = Math.max(max, prices[i] - soFarMin);
- }
- return max;
-}
-```
-
**复制粘贴字符**
[650. 2 Keys Keyboard (Medium)](https://leetcode.com/problems/2-keys-keyboard/description/)
@@ -3516,12 +3519,23 @@ In step 2, we use Paste operation to get 'AA'.
In step 3, we use Paste operation to get 'AAA'.
```
+```java
+public int minSteps(int n) {
+ if (n == 1) return 0;
+ for (int i = 2; i <= Math.sqrt(n); i++) {
+ if (n % i == 0) return i + minSteps(n / i);
+ }
+ return n;
+}
+```
+
```java
public int minSteps(int n) {
int[] dp = new int[n + 1];
+ int h = (int) Math.sqrt(n);
for (int i = 2; i <= n; i++) {
dp[i] = i;
- for (int j = i - 1; j >= 0; j--) {
+ for (int j = 2; j <= h; j++) {
if (i % j == 0) {
dp[i] = dp[j] + dp[i / j];
break;
@@ -3532,16 +3546,6 @@ public int minSteps(int n) {
}
```
-```java
-public int minSteps(int n) {
- if (n == 1) return 0;
- for (int i = 2; i <= Math.sqrt(n); i++) {
- if (n % i == 0) return i + minSteps(n / i);
- }
- return n;
-}
-```
-
## 数学
### 素数
@@ -6660,8 +6664,8 @@ x ^ x = 0 x & x = x x | x = x
位与运算技巧:
- n&(n-1) 去除 n 的位级表示中最低的那一位。例如对于二进制表示 10110 **100** ,减去 1 得到 10110**011**,这两个数相与得到 10110**000**。
+- n&(-n) 得到 n 的位级表示中最低的那一位。-n 得到 n 的反码加 1,对于二进制表示 10110 **100** ,-n 得到 01001**100**,相与得到 00000**100**。
- n-n&(\~n+1) 去除 n 的位级表示中最高的那一位。
-- n&(-n) 得到 n 的位级表示中最低的那一位。-n 得到 n 的反码加 1,对于二进制表示 10110 **100** ,-n 得到 01001**100**,相与得到 00000**100**
移位运算:
@@ -6710,8 +6714,8 @@ The above arrows point to positions where the corresponding bits are different.
public int hammingDistance(int x, int y) {
int z = x ^ y;
int cnt = 0;
- while(z != 0){
- if((z & 1) == 1) cnt++;
+ while(z != 0) {
+ if ((z & 1) == 1) cnt++;
z = z >> 1;
}
return cnt;
@@ -6794,8 +6798,7 @@ diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在重复
public int[] singleNumber(int[] nums) {
int diff = 0;
for (int num : nums) diff ^= num;
- // 得到最右一位
- diff &= -diff;
+ diff &= -diff; // 得到最右一位
int[] ret = new int[2];
for (int num : nums) {
if ((num & diff) == 0) ret[0] ^= num;
@@ -6829,13 +6832,11 @@ private static Map cache = new HashMap<>();
public int reverseBits(int n) {
int ret = 0;
for (int i = 0; i < 4; i++) {
- byte b = (byte) (n & 0b11111111);
ret <<= 8;
- ret |= reverseByte(b);
+ ret |= reverseByte((byte) (n & 0b11111111));
n >>= 8;
}
return ret;
-
}
private int reverseByte(byte b) {