题解 | #数组分组#

package 华为.动态规划01;

import java.util.Scanner;

/*

  • 1.先将数组中3的倍数与5的倍数的数字分别相加并计算他们之间的差值

  • sum3:3的倍数数字相加之和 sum5:5的倍数数字相加之和

  • value = sum3-sum5

  • 2.计算剩余数字的和sum

  • 3.判断sum能否分为差值为value的两组数组

  • <==>sum = sum - value,判断判断剩余的数组+value能否分为和相等的两组数组

  • <==>target = sum/2,判断剩余的数组+value中能否找到若干个数来填充满容积为target的背包(以下的计算方法看leetcode之分割等和子集)

  • (注意这儿数组是带负数的,所以我们要讲剩余的数组中的数和value转化为正数,这样才和leetcode之分割等和子集完全类似)

  • /
    public class 数组分组 {
    public static void main(String[] args) {

      Scanner sc = new Scanner(System.in);
      while(sc.hasNext()){
          //输入数据个数
          int n = sc.nextInt();
          //输入数据
          int[] nums = new int[n];
          for (int i = 0; i < n; i++) {
              nums[i] = sc.nextInt();
          }
          //判断能否分为相等的两个数组
          System.out.println(canPartition(nums));
      }

    }

    private static boolean canPartition(int[] nums) {

      int len = nums.length;
      //1.先将数组中3的倍数与5的倍数的数字分别相加并计算他们之间的差值
      //2.计算剩余数字的和sum
      int[] newNums = new int[2*len];
      int sum3 = 0;
      int sum5 = 0;
      int sum = 0;
      int count = 0;
      int maxValue = Integer.MIN_VALUE;
      for (int i = 0; i < len; i++) {
          if (nums[i]%3==0) {
              sum3 = sum3 + nums[i];
          }else if (nums[i]%5==0){
              sum5 = sum5 + nums[i];
          }else{
              if(nums[i]<0){//负数变正数
                  nums[i] = -nums[i];
              }
              sum = sum + nums[i];
              newNums[count] = nums[i];
              maxValue = nums[i]>=maxValue ? nums[i]:maxValue;
              count = count + 1;
          }
      }
      int value = sum3-sum5;//计算差值
      if (value<0) {
          value = -value;
      }
      //3.判断剩余的数组+value中能否找到若干个数来填充满容积为target的背包
      newNums[count] = value;
      sum = sum + value;
      //判断能否提前退出
      if (count==0) {
          return true;
      }
      if(sum%2!=0){
          return false;
      }
      int target = sum/2;
      if (maxValue>target) {
          return false;
      }
      //递归
      boolean[][] dp = new boolean[count][target+1];
      //边界值
      dp[0][newNums[0]] = true;
      for (int i = 0; i < count; i++) {
          dp[i][0] = true;
      }
      for (int i = 1; i < count; i++) {
          for (int j = 1; j <= target; j++) {
              if (newNums[i]>j) {
                  dp[i][j] = dp[i-1][j];
              }else if(newNums[i]<=j){
                  dp[i][j] = dp[i-1][j] || dp[i-1][j-newNums[i]];
              }
          }
      }
      return dp[count-1][target];

    }
    }

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-26 18:54
说等下个版本吧的发呆爱好者很贪睡:佬最后去了哪家呀
点赞 评论 收藏
分享
面试摇了我吧:啊哈哈面试提前五个小时发,点击不能参加就是放弃
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务