【问题标题】:why checking for multiple conditions returns incorrect results为什么检查多个条件会返回不正确的结果
【发布时间】:2018-03-03 10:02:47
【问题描述】:

给定一个整数数组,是否可以将整数分成两组,使得一组的和是 10 的倍数,而另一组的和是奇数。每个 int 必须在一个组中。编写一个递归帮助器方法,它接受你喜欢的任何参数,并从 splitOdd10() 对你的递归帮助器进行初始调用。 (不需要循环。)

这是我的解决方案代码:(是的,我使用了两种辅助方法而不是一种) 这就是我试图解决问题的方式:(如果我做错了什么,请纠正我)。

nums 中的每个数字只能出现在其中一个组中,group1group2。对于这种情况,元素进入 group1 - group1 += nums[start] 并以这种方式对 nums 中的每个元素进行递归,直到最后一项被传递 - 其中索引 start 超出了 nums - start >= nums.length 的范围.在这样做之后,我们最终在这种可能性“树”中的所有分支的末尾有两个组group1group2。然后检查是否存在两组,其中一组的总和是 10 的倍数,而另一组的总和是奇数 - compare(group1, group2)

我认为这就是我的代码行为不端的地方 - 在对 compare(group1,group2) 的调用中。我尝试如果group1 是 10 的倍数并且 group 2 是奇数 - if( a%10 == 0 && b%2 == 1) return true; 然后,因为我们不知道发生了相反的情况并且 group1 原来是奇数并且 group2 是 10 的倍数,我也检查了if( a%2 == 1 && b%10 == 0 ) return true; 这不适用于所有情况。Here is a screenshot of code output in codingbat.com。但是注释掉compare(group1,group2 的第一个条件可以神奇地修复它。Here is a working code

public boolean splitOdd10(int[] nums) {
 return( splitter(nums,0,0,0) ); 
}
public boolean splitter(int [] nums,int start,  int group1, int group2){
  if (start >= nums.length ) return compare(group1,group2);

  if( splitter(nums,start + 1, group1 += nums[start], group2 ) ) return true; // first condition add element in group1 and recurse on 
  if( splitter(nums,start + 1, group1, group2  += nums[start] ) ) return true;// second condition add element to group2 

  return false;
}

public boolean compare( int a, int b){
  if( a%10 == 0  && b%2 == 1) return true;// <--- if I remove this line the code works
  if( a%2 == 1 && b%10 == 0 ) return true;
  return false;
}

我的问题是:我们如何“知道”检查哪个组是奇数以及检查哪个组是 10 的倍数?我检查了两个组的两种情况,但显然这是错误的,并且没有为某些数组返回正确的结果。例如,它为数组 [10,0,5,5] 返回“true”,而不是“false”。请帮助我理解为什么检查这两种情况都不正确。

【问题讨论】:

  • += 是一个修改操作。这意味着您计算的group1 += nums[start] 在第一个if 修改 group1 中传递给splitter,因此您在第二次调用splitter 时看到修改后的值。这是故意的吗?
  • 您需要在这里做的第一件事是使用调试器逐行执行您的代码。检查每个方面、每个局部变量、每个返回值等是否符合您的预期。
  • 我觉得不仅仅是编码问题...
  • 不一定可以根据这些规则将整数集合分成两组。以下是示例:{1}、{1,2}、...、{10, 12}、{12, 13}...
  • 抱歉,@T.J.Crowder,是的,这是故意的。我的思路是这样的:对于数组 nums 的每个“元素”,有两种可能性:要么进入 group1(因此是 group1 += nums[start] 或另一个。

标签: java recursion


【解决方案1】:

嗯,从算法上讲,这很容易。

给定一个整数集合,它们的总和可能是奇数或偶数。

  • 如果它们总和为奇数,一种可能的拆分是将所有数字返回到 sumIsOdd-bucket,而 sumMod10-bucket 保持为空。
  • 如果它们总和为 10 的倍数,这是偶数和的一种特殊情况,一个有效的解决方案是将它们全部排序到 sumIsMod10 存储桶中,而奇数存储桶保持为空。但是奇数桶是空的,加起来不是奇数,所以这不是解决方案,而是失败。
  • 第三种可能性是,总和是偶数,但不能被 10 整除,那么无论我们多久从总和中减去 10,(甚至不检查,如果某些数字加起来等于这样的总和),余数之和既不会是奇数,也不能被 10 整除。例如:36→26→16→6 - 没有余数是奇数,也不能被 10 整除。
  • 最后一种可能性是,我们从一个本身不能被 10 整除的偶数和中减去一个偶数,然后将其放入奇数桶中。但是,即使我们在另一个桶中达到可被 10 整除的总和,奇数桶也会是偶数并且也会失败。示例:(100, 1) 可以拆分为 (1)(100),但 (101)() 也是一种解决方案。

所以唯一可能的解决方案是总和已经是奇数,将所有元素放入奇数桶是一个有效的答案,因为 0%10 是 0。

因此,您可以在第一步将其拆分为一个空白部分,另一侧为整个内容,或者它不可拆分。

一个更复杂的问题是,找到两个总和或元素计数差异最小的桶。

【讨论】:

  • 谢谢,您提供了一种以难以置信的简单方式解决问题的方法。
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多