1.不同路径2
public class DifferentPath2 {
public static void main(String[] args) {
System.out.println(uniquePathsWithObstacles(new int[][] {{0,0,0},{0,1,0},{0,0,0}}));
}
public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
int n = obstacleGrid.length;
int m = obstacleGrid[0].length;
int[] dp = new int[m];
//起点可能有障碍物
dp[0] = (obstacleGrid[0][0] == 1) ? 0 : 1;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
//有障碍物的格子直接赋0
if(obstacleGrid[i][j] == 1) {
dp[j] = 0;
}
//否则dp[j]的值由左方和上一次迭代的dp[j]累加而来
else if(obstacleGrid[i][j] == 0 && j - 1 >= 0) {
dp[j] = dp[j] + dp[j - 1];
}
}
}
return dp[m - 1];
}
2.整数拆分
public class IntegerSplitting {
public static void main(String[] args) {
System.out.println(integerBreak(2));
}
public static int integerBreak(int n) {
if(n <= 3) return n - 1;
int a = n / 3, b = n % 3;
if(b == 0) return (int)Math.pow(3, a);
if(b == 1) return (int)Math.pow(3, a - 1) * 4;
return (int)Math.pow(3, a) * 2;
}
}
3.最长奇偶数组
public class LongestOddEvenGroup {
public static void main(String[] args) {
System.out.println(longestAlternatingSubarray(new int[] {3,2,5,4},5));
}
public static int longestAlternatingSubarray(int[] nums, int threshold) {
int n = nums.length;
int ans = 0, i = 0;
while (i < n) {
if (nums[i] > threshold || nums[i] % 2 != 0) {
i++; // 直接跳过
continue;
}
int start = i; // 记录这一组的开始位置
i++; // 开始位置已经满足要求,从下一个位置开始判断
while (i < n && nums[i] <= threshold && nums[i] % 2 != nums[i - 1] % 2) {
i++;
}
// 从 start 到 i-1 是满足题目要求的(并且无法再延长的)子数组
ans = Math.max(ans, i - start);
}
return ans;
}
}
4.分割等和子集
public class DivideEqualSumSubsets {
public static void main(String[] args) {
System.out.println(canPartition(new int[]{1, 5, 11, 5}));
}
public static boolean canPartition(int[] nums) {
int sum = 0, maxNum = 0;
for (int num : nums) {
sum += num;
maxNum = Math.max(maxNum, num);
}
if (sum % 2 != 0 || maxNum * 2 > sum) {
return false;
}
int n = nums.length;
int target = sum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true;
for (int i = 1; i <= n; i++) {
for (int j = target; j >= nums[i - 1]; j--) {
dp[j] |= dp[j - nums[i - 1]];
}
}
return dp[target];
}
}
5.最后一块石头的重量2
public class TheWeightOfTheLastStone2 {
public static void main(String[] args) {
System.out.println(lastStoneWeightII(new int[]{2, 7, 4, 1, 8, 1}));
}
public static int lastStoneWeightII(int[] stones) {
if (stones == null || stones.length <= 0) {
return 0;
}
int sum = 0;
for (int stone : stones) {
sum += stone;
}
// 根据推导,当石头最小可能重量时,最好子集数组石头的总重量,趋近于 且 最大为 sum / 2
int maxWeight = sum / 2;
int length = stones.length;
boolean[] dp = new boolean[maxWeight + 1]; // dp[i] 表示,是否有子集数组,重量和为i
dp[0] = true;
for (int stone : stones) {
for (int i = maxWeight; i >= stone; i--) {
dp[i] = dp[i] || dp[i - stone];
}
}
// 从 最大值 开始,遍历dp数组,寻找最大i的值
for (int i = maxWeight; ; i--) {
if (dp[i]) {
return sum - 2 * i; // 根据数学推导,计算result
}
}
}
}
结束。