refactor(redoAll): 优化动态规划实现及新增解决方案

- 重构`LeetCode209`,添加`Solution1`类,采用前缀和与二分搜索的解法。
- 新增`LeetCode279`,提供两种解决方案,包括一维和二维动态规划方法。
- 对`LeetCode713`进行微调,优化注释和代码清晰度。
- 新增`LeetCode1049`,提出两种动态规划解法,包括完全背包和0-1背包实现。
This commit is contained in:
whaifree 2024-08-20 23:57:37 +08:00
parent f5ac4f8829
commit 1acabb1909
4 changed files with 210 additions and 1 deletions

View 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;
}
}

View File

@ -2,6 +2,8 @@ package cn.whaifree.redo.redoAll;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays;
/** /**
* @version 1.0 * @version 1.0
* @Author whai文海 * @Author whai文海
@ -14,7 +16,7 @@ public class LeetCode209 {
public void test() { public void test() {
int[] nums = {1,2,3,4,5}; int[] nums = {1,2,3,4,5};
int target = 11; int target = 11;
int minSubArrayLen = new Solution().minSubArrayLen(target, nums); int minSubArrayLen = new Solution1().minSubArrayLen(target, nums);
System.out.println(minSubArrayLen); System.out.println(minSubArrayLen);
} }
@ -39,4 +41,28 @@ public class LeetCode209 {
return minLength == Integer.MAX_VALUE ? 0 : minLength; 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;
}
}
} }

View 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];
}
}
}

View File

@ -51,7 +51,9 @@ public class LeetCode713 {
} }
right++; right++;
res += right - left; res += right - left;
} }
return res; return res;
} }
} }