在GoLang的HouseRobber编程任务中存在错误。

huangapple go评论86阅读模式
英文:

Bug in HouseRobber Programming Task in GoLang

问题

问题陈述非常简单:

给定一个整数列表,返回非相邻元素的最大和

例如 houseRobber([5,0,0,5]) => 10houseRobber([2,1,2]) => 4

我决定采用两个部分的解决方案:

  1. 生成所有可行的索引列表

    (例如 [5,0,0,5] => [[0,2],[0,3],[1,3]]

  2. 确定给定索引集合上元素的最大和。

    (例如 [5,0,0,5],[[0,2],[0,3],[1,3]] => 10

所以我开始实现我的解决方案。我将脚本命名为main,并包含了一个我自己的失败测试,以便任何人都可以在自己的计算机上轻松运行它。

package main
import(
    "fmt"
)
/*
concat函数将两个整数数组的数组连接起来。
*/
func concat(a,b [][]int) [][]int{
    for _,k := range b{
        a = append(a,k)
    }
    return a
}
/*
helper函数接受一个已包含在给定子集中的整数数组inGroup和一个整数lastHouse,该整数是数组的最大索引,它返回表示所有可能的非相邻元素索引集合的整数数组的数组,包括inGroup中提供的索引。
*/
func helper(inGroup []int,lastHouse int) [][]int{
    if len(inGroup) == 0 {
        return concat(helper([]int{0},lastHouse),helper([]int{1},lastHouse))
    }
    highest := inGroup[len(inGroup)-1]
    if highest <= (lastHouse-3){
        return concat(helper(append(inGroup,highest+2),lastHouse),
                      helper(append(inGroup,highest+3),lastHouse))
    }
    if highest==lastHouse-2{
        return [][]int{append(inGroup,highest+2)}
    }
    return [][]int{inGroup}
}
/*
saturated函数是helper函数的包装函数,它完成了大部分的工作。
*/
func saturated(n int) [][]int{
    return helper([]int{},n-1)
}
/*
subSetSum函数接受一个整数列表和一个索引列表,返回给定索引处元素的和。
*/      
func subSetSum(values, indicies []int) int{
    ret := 0
    for _,k := range indicies{
        ret += values[k]
    }
    return ret
}
/*
houseRobber函数是主方法,接受一个数字数组并返回一个整数,即非相邻元素的最大和。
*/
func houseRobber(nums []int) int{
    if(len(nums) == 0){
        return 0
    }
    if(len(nums) == 1){
        return nums[0]
    }
    combos := saturated(len(nums))
    temp := 0
    ret := 0
    bestCombo := 0
    for n,k := range combos{
        temp = subSetSum(nums,k)
        if temp > ret {
            ret = temp
            bestCombo = n
        }
    }
    fmt.Println(combos[bestCombo])
    return ret
}

func main(){
        houseRobber([]int{1,2,3,4,5,6,7,8,9,10,11,12,13,14})
        houseRobber([]int{1,2,3,4,5,6,7,8,9,10,11,12,13,
                  14,15,16,17,18,19,20,21,22,23,24,25,26})
}

输出结果为[1 3 5 7 9 12 13][1 3 5 7 9 11 13 15 17 20 23 25 25],这些是确定具有最大和的非相邻索引。**但是等等!**12和13是相邻的!这是怎么发生的?只有最高值+2和最高值+3被附加到inGroup数组中,然而10和11都不包含在数组中,那么13是怎么出现的呢?此外,第二个结果中额外的25似乎也超出了我认为应该发生的范围。例如,如果只附加了最高值+2和最高值+3,那么为什么会附加最高值+0到inGroup中?

显然,这个错误导致一些测试失败,但问题并不普遍,因为大多数测试都通过了。

我确定这里有一个解释,但目前我还没有想到。

英文:

The Problem statement is fairly simple:

> Given a list of integers return the maximum sum of non adjacent
> elements.

. For example houseRobber([5,0,0,5]) =&gt; 10 and houseRobber([2,1,2]) =&gt; 4

> One solution I decided on has 2 parts:

  1. Generate all viable index lists

    (eg [5,0,0,5] =&gt; [[0,2],[0,3],[1,3]])

  2. Identify the maximum sum of elements at a given set of indices.

    (eg [5,0,0,5],[[0,2],[0,3],[1,3]] =&gt; 10)

So I went forth and implemented my solution. I've made the script package main and included a my own failing test so that anyone can easily run it themselves on their own machine.

package main
import(
&quot;fmt&quot;
)
/*
concat takes 2 arrays of integer arrays and concatonates them.
*/
func concat(a,b [][]int) [][]int{
for _,k := range b{
a = append(a,k)
}
return a
}
/*
helper takes an array of integers inGroup which have been included to a given
sub set and an integer lastHouse which is the maximum index for the array it 
returns the array of integer arrays representing all possible sets of indices 
for non adjacent elements including the indicies provided in inGroup.
*/
func helper(inGroup []int,lastHouse int) [][]int{
if len(inGroup) == 0 {
return concat(helper([]int{0},lastHouse),helper([]int{1},lastHouse))
}
highest := inGroup[len(inGroup)-1]
if highest &lt;= (lastHouse-3){
return concat(helper(append(inGroup,highest+2),lastHouse),
helper(append(inGroup,highest+3),lastHouse))
}
if highest==lastHouse-2{
return [][]int{append(inGroup,highest+2)}
}
return [][]int{inGroup}
}
/*
saturated is a wrapper function for the helper that does the heavy lifting. 
*/
func saturated(n int) [][]int{
return helper([]int{},n-1)
}
/*
Given a list of integers and a list of indicies the subSetSum function returns 
the sum of the elements at the given indicies.
*/      
func subSetSum(values, indicies []int) int{
ret := 0
for _,k := range indicies{
ret += values[k]
}
return ret
}
/*
houseRobber is the main method, taking an array of numbers and returning an integer, 
the max sum of non adjacent elements
*/
func houseRobber(nums []int) int{
if(len(nums) == 0){
return 0
}
if(len(nums) == 1){
return nums[0]
}
combos := saturated(len(nums))
temp := 0
ret := 0
bestCombo := 0
for n,k := range combos{
temp = subSetSum(nums,k)
if temp &gt; ret {
ret = temp
bestCombo = n
}
}
fmt.Println(combos[bestCombo])
return ret
}
func main(){
houseRobber([]int{1,2,3,4,5,6,7,8,9,10,11,12,13,14})
houseRobber([]int{1,2,3,4,5,6,7,8,9,10,11,12,13,
14,15,16,17,18,19,20,21,22,23,24,25,26})
}

prints: [1 3 5 7 9 12 13] & [1 3 5 7 9 11 13 15 17 20 23 25 25] as the non-adjacent indices determined to have maximum sum. But wait! 12 and 13 are adjacent! How did that happen? The only thing appended to the inGroup arrays are the highest +2 and the highest +3, however neither 10 or 11 are contained by the array so how does 13 get there? Additionally the extra 25 on the end of the second result also seems to escape the bounds of what I think should be happening. E.g. How is highest+0 getting appended to inGroup if highest+2 and highest+3 are the only values being appended?

> Obviously this bug is causing some tests to fail but the problem is
> not ubiquitous, as a majority of tests pass.

I am sure there is an explanation here but at the moment it is escaping me.

答案1

得分: 1

似乎你在使用append函数时遇到了一个微妙的问题。

在你的函数中,你不应该使用append来创建新的数组。

相反,你应该复制数组,并将值附加到复制的数组中。

如果你将调用append替换为以下定义的copyAndAppend函数:

func copyAndAppend(i []int, vals ...int) []int {
j := make([]int, len(i), len(i)+len(vals))
copy(j, i)
return append(j, vals...)
}

你的代码似乎可以正常工作。

更多详情请参考:

https://stackoverflow.com/questions/35276022/unexpected-slice-append-behaviour

英文:

It seems you hit a subtle issue with the append function.

You should not be using append to create new arrays as you are doing in your function.

Instead, copy them and append the values to the copied array.

If you replace your calls to append to copyAndAppend as defined here:

func copyAndAppend(i []int, vals ...int) []int {
j := make([]int, len(i), len(i)+len(vals))
copy(j, i)
return append(j, vals...)
}

Your code seems to work correctly.

See here for more details:

https://stackoverflow.com/questions/35276022/unexpected-slice-append-behaviour

huangapple
  • 本文由 发表于 2017年7月21日 01:52:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/45221912.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定