Go语言实现Square sums (simple)

描述:

Write function square_sums_row (or squareSumsRow/SquareSumsRow depending on language rules) that, given integer number N (in range 2…43), returns array of integers 1…N arranged in a way, so sum of each 2 consecutive numbers is a square.
Solution is valid if and only if following two criterias are met:
Each number in range 1…N is used once and only once.
Sum of each 2 consecutive numbers is a perfect square.
Example
For N=15 solution could look like this:
[ 9, 7, 2, 14, 11, 5, 4, 12, 13, 3, 6, 10, 15, 1, 8 ]

分析:

如果系统学习过深度优先搜索(DFS),应该很自然地想到用DFS求解该问题。此问题不需要遍历所有路径,只需搜索到一条满足条件的路径即可。
具体来说,以N=15为例,最终结果应该是包含15个数的序列。第一个数有可能是[1, 15]中的任何一个。首先从1开始遍历。此时第二个数必须满足以下条件:
1. 属于[1, 15]中除去前面步骤已占用的数字;
2. 和结果序列前一个数字的和为某整数平方和。
依条件,第二个数不能是1,因为1已被结果序列前面的位置占用;也不能是2,因为2和序列前一个数字1的和是3,开方不是整数。3是备选项,因为3没有被结果序列前面位置所占用,同时和序列前一个数字1的和是4,是2的平方。此时结果序列暂定为[1, 3]。按照以上步骤反复推进,直到[1, 3, 6, 10, 15]。此时在位置6上,剩余可选的数字分别是:2, 4, 5, 7, 8, 9, 11, 12, 13, 14。这些数字与当前结果序列最后一个数字15相加,都无法成为整数的平方。此时说明:结果序列第5个位置不能是15。因此我们从位置6回溯到位置5,此时在位置5上,之前已经遍历过了1到14,都不满足要求,15又因为后续无以为继而放弃,已没有合适的数放置,因此我们继续回溯,回溯到位置4。位置4之前是10,此时说明位置4不能是10,剩余可选数字是11, 12, 13, 14, 15。很遗憾,这5个数字和此时结果序列前一个数字6的和无法构成整数的平方,因此必须继续回溯。回溯到位置3,此时从7开始寻找下一个满足条件的数字,我们发现13是满足条件的数字。以13作为第三个位置上的数字,此时结果序列暂定为[1, 3, 13],继续向后递归遍历,直到所有15个位置都被放置数字。
回溯深度优先查找算法的代码基本框架是:

func dfs(step int) {
    if 所有步骤/位置都已满足要求 {
        收尾工作
        返回
    }
    for 数据 := range 备选集合 {
        if 数据满足检索条件 {
            以该数据填充目标集合
            标记满足检索条件的数据已被占用,在后续step中,该数据不可用
            dfs(step + 1)
            回溯至此,把该数据从目标集合中剔除,准备从备选集合中继续检索作为当前step满足条件的数据
            标记满足检索条件的数据未被占用,以便深入后续step时,该数据可用
        }
    }
}

实现:

var (
  square = []int{81, 64, 49, 36, 25, 16, 9, 4}
  found bool
  result []int
  used []bool
)

func inSlice(si []int, n int) bool {
  for _, v := range si { if v == n { return true } }
  return false
}

func dfs(n, step int) {
  if step == n + 1 {
    found = true
    return
  }
  for i := 1; i <= n; i++ {
    if step == 1 || used[i] == false && inSlice(square, result[len(result) - 1] + i) {
      result, used[i] = append(result, i), true
      dfs(n, step + 1)
      if found { return }
      result, used[i] = result[:len(result)-1], false
    }
  }
}

func SquareSumsRow(n int) []int {
  found, result, used = false, make([]int, 0), make([]bool, n + 1)
  dfs(n, 1)
  if len(result) != n { return nil }
  return result
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值