题解 | #农场的奶牛分组#
农场的奶牛分组
https://www.nowcoder.com/practice/bdb90a97a15d42f989e406080d88bed9?tpId=354&tqId=10595842&ru=/exam/oj&qru=/ta/interview-202-top/question-ranking&sourceUrl=%2Fexam%2Foj
先求得奶牛的总体重sum,然后找到一个目标值target,使得分成两组的奶牛体重和都等于target。
首先,我们需要检查是否满足可以将奶牛分成两组的条件。如果奶牛的总数小于2,或者总体重不能被2整除,那么无法分成两组,直接返回false。
然后,我们可以定义一个二维数组dp,dp[i][j]表示在前i头奶牛中是否存在一个分组,使得体重之和等于j。
初始状态为dp[0][0] = true,表示前0头奶牛的体重之和为0,是成立的。
接下来,我们可以进行动态规划的转移。对于第i头奶牛,我们有两种选择:将其加入一个组,或者不加入组。如果加入组,那么相应的状态变化为dp[i][j] = dp[i-1][j-weight[i]](前i头牛的状态=前i-1头牛在(体重=j-第i头牛的体重)的状态),
其中weight[i]表示第i头奶牛的体重。如果不加入任何组,状态保持不变,即dp[i][j] = dp[i-1][j]。
最终,我们需要检查dp[n][target]是否为true,其中n为奶牛数量
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param weights int整型一维数组
* @return bool布尔型
*/
public boolean canPartition (int[] weights) {
// write code here
int n = weights.length;
int sum = Arrays.stream(weights).sum();
// 无法分为两组
if (n < 2 || sum % 2 != 0) {
return false;
}
int target = sum / 2;
// dp[i][j]表示在前i头奶牛中是否存在一个分组,使得体重之和为j
boolean[][] dp = new boolean[n + 1][target + 1];
// 表示前0头牛的体重之和为0可以分组
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= target; j++) {
// 第i头牛不加入分组
dp[i][j] = dp[i - 1][j];// 与上一次保持一致
if (j >= weights[i - 1]) {// 第i头牛的体重<=j<=target
// 加入分组,状态=dp[i-1][j-weights[i-1]](前i-1头牛在(j-当前牛的体重)的分组状态)
dp[i][j] |= dp[i - 1][j - weights[i - 1]];
}
}
}
return dp[n][target];
}
}
计算整个数组的元素和。如果和为奇数,那么无法分为两个和相等的子集,因此返回false。
然后,要将问题转换为是否存在一个子集,使得它的和等于整个数组的和的一半,也就是target。
使用动态规划的方法来解决这个问题。定义一个布尔数组dp,其中dp[i]表示是否存在一个子集的和等于i。初始时,设置dp[0]为true,因为和为0的子集总是存在的。
接下来,遍历整个weights数组。对于数组中的每个元素weight,从target开始逆序更新dp数组。如果dp[i-weight]为true,那么说明存在一个子集的和等于i-weight,那么将dp[i]设置为true。
最后,返回dp[target]的值,表示是否存在一个子集的和等于target。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param weights int整型一维数组
* @return bool布尔型
*/
public boolean canPartition (int[] weights) {
// write code here
int n = weights.length;
int sum = Arrays.stream(weights).sum();
// 无法分为两组
if (n < 2 || sum % 2 != 0) {
return false;
}
int target = sum / 2;
// 是否存在一组的和=i
boolean[] dp = new boolean[target + 1];
// 和为0的子集存在
dp[0] = true;
for(int weight:weights){
// 若dp[i-weight]==true,则dp[i]=true
// i<weight时,和为i的子集不存在
for(int i=target;i>=weight;--i){
dp[i] |= dp[i-weight];
}
}
return dp[target];
}
}
面试高频TOP202题解
查看1道真题和解析