refactor(redoAll): 优化动态规划实现及新增解决方案
- 重构`LeetCode209`,添加`Solution1`类,采用前缀和与二分搜索的解法。 - 新增`LeetCode279`,提供两种解决方案,包括一维和二维动态规划方法。 - 对`LeetCode713`进行微调,优化注释和代码清晰度。 - 新增`LeetCode1049`,提出两种动态规划解法,包括完全背包和0-1背包实现。
This commit is contained in:
parent
f5ac4f8829
commit
1acabb1909
111
src/main/java/cn/whaifree/redo/redoAll/LeetCode1049.java
Normal file
111
src/main/java/cn/whaifree/redo/redoAll/LeetCode1049.java
Normal file
@ -0,0 +1,111 @@
|
||||
package cn.whaifree.redo.redoAll;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/8/20 22:11
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode1049 {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
int[] arr = new int[]{2,7,4,1,8,1};
|
||||
int i = lastStoneWeightII1(arr);
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* dp[i][j] 表示从0-i中任意取,放入j获取的最大价值
|
||||
*
|
||||
* half 为背包容量
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7 8 9 1011
|
||||
* index 0: 0 0 2 2 2 2 2 2 2 2 2 2
|
||||
* index 1: 0 0 2 2 2 2 2 2 2 2 2 9
|
||||
* index 2: 0 0 2 2 2 2 2 2 2 2 2 9
|
||||
* index 3: 0 0 2 2 2 2 2 2 2 2 2 9
|
||||
* index 4: 0 0 2 2 2 2 2 2 2 2 2 10
|
||||
* index 5: 0 0 2 2 2 2 2 2 2 2 2 10
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param stones
|
||||
* @return
|
||||
*/
|
||||
public int lastStoneWeightII(int[] stones) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < stones.length; i++) {
|
||||
sum += stones[i];
|
||||
}
|
||||
|
||||
int half = sum / 2;
|
||||
int[][] dp = new int[stones.length][half + 1];
|
||||
for (int i = stones[0]; i <= half; i++) {
|
||||
dp[0][i] = stones[0];
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i < stones.length; i++) {
|
||||
for (int j = 1; j <= half; j++) {
|
||||
// 够放
|
||||
if (j >= stones[i]) {
|
||||
// 放入 dp[i-1][j-nums[i]]+value[i]
|
||||
// 不放 dp[i-1][j]
|
||||
dp[i][j] = Math.max(dp[i - 1][j - stones[i]] + stones[i], dp[i - 1][j]);
|
||||
} else {
|
||||
dp[i][j] = dp[i - 1][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return sum - dp[stones.length - 1][half] * 2;
|
||||
}
|
||||
|
||||
|
||||
public int lastStoneWeightII1(int[] stones) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < stones.length; i++) {
|
||||
sum += stones[i];
|
||||
}
|
||||
|
||||
int half = sum / 2;
|
||||
int[] dp = new int[half + 1];
|
||||
// for (int i = stones[0]; i <= half; i++) {
|
||||
// dp[i] = stones[0];
|
||||
// }
|
||||
|
||||
for (int i = 0; i < stones.length; i++) {
|
||||
for (int j = half; j >= stones[i]; j--) {
|
||||
// 够放
|
||||
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 如果我们从前往后遍历:
|
||||
* for (int j = stones[i]; j <= half; j++) {
|
||||
* dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
|
||||
* }
|
||||
* 在这种情况下,当我们计算 dp[j] 时,dp[j - stones[i]] 可能已经被当前轮次的更新所影响。
|
||||
* 这意味着我们可能会错误地使用当前轮次中已经更新的值,而不是上一轮次的值。这会导致结果不正确。
|
||||
*
|
||||
* 当我们计算 dp[j] 时,dp[j - stones[i]] 仍然是上一轮次的结果,因为我们在更新 dp[j] 之前还没有更新
|
||||
* dp[j - stones[i]]。这确保了我们使用的是正确的历史数据,从而得到正确的结果。
|
||||
*/
|
||||
|
||||
/**
|
||||
* [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||
* [0, 0, 2, 2, 2, 2, 2, 7, 7, 9, 9, 9]
|
||||
* [0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9, 11]
|
||||
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
*/
|
||||
|
||||
return sum - dp[half] * 2;
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package cn.whaifree.redo.redoAll;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
@ -14,7 +16,7 @@ public class LeetCode209 {
|
||||
public void test() {
|
||||
int[] nums = {1,2,3,4,5};
|
||||
int target = 11;
|
||||
int minSubArrayLen = new Solution().minSubArrayLen(target, nums);
|
||||
int minSubArrayLen = new Solution1().minSubArrayLen(target, nums);
|
||||
System.out.println(minSubArrayLen);
|
||||
}
|
||||
|
||||
@ -39,4 +41,28 @@ public class LeetCode209 {
|
||||
return minLength == Integer.MAX_VALUE ? 0 : minLength;
|
||||
}
|
||||
}
|
||||
|
||||
class Solution1{
|
||||
public int minSubArrayLen(int target, int[] nums) {
|
||||
int[] preSum = new int[nums.length + 1];
|
||||
|
||||
for (int i = 1; i < preSum.length; i++) {
|
||||
preSum[i] = preSum[i - 1] + nums[i - 1];
|
||||
}
|
||||
|
||||
int minLen = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < preSum.length; i++) {
|
||||
// preSum[right] = target + preSum[i]
|
||||
int fill = target + preSum[i];
|
||||
int right = Arrays.binarySearch(preSum, fill);
|
||||
if (right < 0) {
|
||||
right = -right - 1;
|
||||
}
|
||||
if (right < preSum.length) {
|
||||
minLen = Math.min(minLen, right - i);
|
||||
}
|
||||
}
|
||||
return minLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
src/main/java/cn/whaifree/redo/redoAll/LeetCode279.java
Normal file
70
src/main/java/cn/whaifree/redo/redoAll/LeetCode279.java
Normal file
@ -0,0 +1,70 @@
|
||||
package cn.whaifree.redo.redoAll;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/8/20 23:30
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode279 {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int n = 13;
|
||||
int i = new Solution().numSquares(n);
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
class Solution {
|
||||
/**
|
||||
* dp[j] 表示容量为j的背包需要几个完全平方数,可以填满
|
||||
*
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public int numSquares(int n) {
|
||||
int pakage = n + 1;
|
||||
int[] dp = new int[pakage];
|
||||
for (int i = 1; i <= n; i++) {
|
||||
dp[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 2; i <= n; i++) {
|
||||
for (int j = i * i; j <= n; j++) {
|
||||
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return dp[n];
|
||||
}
|
||||
}
|
||||
|
||||
class Solution1 {
|
||||
/**
|
||||
* dp[j] 表示容量为j的背包需要几个完全平方数,可以填满
|
||||
*
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public int numSquares(int n) {
|
||||
int pakage = n + 1;
|
||||
int x = (int) Math.floor(Math.sqrt(n));
|
||||
int[][] dp = new int[x + 1][pakage];
|
||||
for (int i = 0; i <= n; i++) {
|
||||
dp[1][i] = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= x; i++) {
|
||||
for (int j = i; j <= n; j++) {
|
||||
dp[i][j] = dp[i - 1][j];
|
||||
if (j >= i * i)
|
||||
dp[i][j] = Math.min(dp[i][j - i * i] + 1, dp[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
return dp[x][n];
|
||||
}
|
||||
}
|
||||
}
|
@ -51,7 +51,9 @@ public class LeetCode713 {
|
||||
}
|
||||
right++;
|
||||
res += right - left;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user