【问题标题】:Given elements in a array find combinations that equal destination value给定数组中的元素找到等于目标值的组合
【发布时间】:2014-09-12 15:07:38
【问题描述】:

我一直在思考这个问题很长一段时间,但由于某种原因,它没有引起我的注意。如果给我一个数组 [1,2,3,4] 和一个目标值为 5。我想从数组中获取所有可能的组合,以便它们添加到目标值。

所以我能想到的一种方法是

1!=5
1+2!=5
1+3!=5
1+4=5
//now check with combos of 3 digits.
1+2+3 !=5
1+2+4 !=5
//now check with combos of 4...however at this point i realized i missed the combination 1+3+4 also.

我在网上看到了一些答案,但它们似乎没有意义,我对其他答案或代码并不真正感兴趣,我想学习如何以正确的方式思考,这样我就可以解决这些问题。我想知道是否有人可以指导我并帮助我解决这个问题,以及我应该如何思考解决这些问题。在这一点上,我并不真正担心效率,因为我什至无法制定一种方法,所以欢迎所有方法。此外,我更喜欢只使用数组和普通循环,而不是像哈希这样的任何其他数据结构,因为我还没有学过这些。

【问题讨论】:

  • 您可能想要枚举原始数组的所有“子集”,并检查其中的总和为 5。
  • @phimuemue 你能详细说明一下吗?我不太清楚你的意思。
  • @user2733436:理解集合论的语言(集合、子集、并集、交集等)对于思考这样的算法至关重要。我建议在网上或数学教科书中找到介绍。幸运的是,没有什么要学的:)
  • 在处理这样的问题时,考虑如何操作数据以使问题变得更容易也很有帮助。例如,当数字数组按升序与随机顺序排序时,这个问题更容易解决。递归在将大集合分解为较小集合的这类问题中也很有用。

标签: java arrays algorithm recursion


【解决方案1】:

既然你说你想要“思维方式”,这是一种方式。

您从最简单的案例开始,做出各种假设

1) 假设所有数组元素都小于目标值。 -- 一个简单的验证将在实施完成时有所帮助。

高级步骤

你需要找到一种方法来获得数字的所有可能排列。

然后添加排列的每个元素并检查总和是否匹配'destination'(这是更简单的任务)

现在面临主要挑战:

如何获得所有可能的排列?

解决方法 假设我们有一个单元素数组: 解决方案很明显:)

接下来我们有一个包含两个元素的数组: 您确定数组的大小:2 您必须迭代此大小,因为您的组合将小于或等于此大小。 您的第一次迭代将具有值 1。即。您正在寻找尺寸一的组合 这很简单:你一个一个地遍历数组。

下一次迭代将寻找大小为 2 的组合。 由于迭代值 (2) 等于数组的大小 (2),因此您知道只有一种可能的情况。

现在让我们处理一个大小为 3 的数组:

对于大小 1 的排列,您知道该怎么做。

对于大小 3 的排列,您知道组合是什么。

对于大小为 2 的排列,您需要再次迭代。 您遍历数组,保存数组的当前元素并置换大小为 2 的数组的其余部分。

接下来,您遍历第二个和第三个元素,并对大小为 (3-1 = 2) 的数组的其余部分进行置换

--------------------------------已更新---------- ---------------------------------------

接下来让我们尝试一个有 4 个元素的数组 让我们调用是 A(4)

对于大小 1 排列和大小 4 排列,这是显而易见的。

对于大小为 3 的排列,您将重复为获得大小为 3 的数组的大小为 2 的排列所做的过程。 你将持有一个元素,你将得到一个大小为 3 的数组。姑且称之为 A(3)

但请记住,您还需要大小为 2 的排列。您可以通过应用相同的可重用组件,从这个大小为 3 的数组本身确定大小为 2 的所有排列。这变成了一个递归调用。

所以本质上,你大部分时间都必须做一件事。

'如果你有一个大小为 n 的数组; A(n),你需要遍历它,保持被迭代的元素,你将拥有一个大小为 n-1 的数组; A(n-1)'

然后再次进行递归调用。 并将粗线中的 n 替换为 n-1

所以基本上正如你所见,这变成了一个递归问题。

这是解决此问题的一种思路。我希望我清楚地解释了思考的过程。

------------------------------示例- ------------------------------------------

假设我们有一个数组 {1,2,3,4,5}

我们的函数看起来像

 function G (int[] array ) {
   Looping over array{ 
       remove array[index] from array
        you are left with restOfTheArray .// store it some where.
       then
          make a recursive call to G with restOfTheArray; 
     }
 }

循环试运行:

 Dry run 1:
  funtion G (Array (n ) ) {
    Looping over {1,2,3,4,5}{ 
        first value while looping is 1, remove it from the array;
        you have {2,3,4,5}.// store it some where.
       then
          make a recursive call to G with {2,3,4,5}
     }
 } 


  Dry run 2: 
funtion G (Array (n ) ) {
   Looping over {1,2,3,4,5}{ 
       second value while looping is 2, remove it from the array;
        you have {1,3,4,5}.// store it some where.
       then
          make a recursive call to G with {1,3,4,5}
     }
 }

等等……

现在让我们看看递归调用的试运行:

  Dry Run 1.1
 funtion G (Array (n ) ) {
   Looping over {1,2,3,4,5}{ 
       First value while looping is 1, remove it from the array;
        you have {2,3,4,5}.// store it some where.
       then
          make a recursive call to G with {2,3,4,5}
     }
 }

 Dry Run 1.2 

 funtion G (Array (n ) ) {
   Looping over {2,3,4,5}{ 
       First value while looping is 2, remove it from the array;
        you have {3,4,5}.// store it some where.
       then
          make a recursive call to G with {3,4,5}
     }
 }

等等……

【讨论】:

  • 我不明白你为什么在一开始就做出假设,例如固定元素大小以及数组值小于目标值
  • 很抱歉让您感到困惑。我在旅途中想出了解决方案。我首先简化了脑海中的问题,这样我的思维就不会被阻塞。 :)
  • 我编辑了这些假设。基本上,关于假设的想法是,当开始解决问题时,假设一些事情有时是个好主意,这样人们就可以将注意力集中到问题的核心部分。解决它,然后一一消除假设并不断修改解决方案。
  • np!所以我认为你的答案应该从解决方案中读取......我仍然不清楚它是如何递归工作的
  • 我澄清了答案中的递归部分。现在请再看看答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2020-04-17
  • 1970-01-01
  • 1970-01-01
  • 2019-06-27
  • 1970-01-01
  • 2014-05-26
相关资源
最近更新 更多