【问题标题】:Finding pair arrangement in Go在 Go 中查找配对排列
【发布时间】:2019-10-19 06:40:59
【问题描述】:

在这里,我试图形成一个排列,其中包含成对的数字,每对 mm 元素分隔。例如:

  • 对于 [0,2],配对排列为 [2,0, 0,2],因此 m=2,因此数字 2 由 2 个元素分隔。
  • 对于 [0,1] = 没有有效的安排

我仍然无法找出排列的模式或算法,因为我需要找到直到 [0,1,2,3,4,5,6,7,8] 的排列。但是,此列表的有效安排是 [3,7,8,2,3,1,2,1,6,7,5,8,4,0,0,6,5,4] 手动进行。

在下面的代码中,我只能通过首先获取列表中最大的数字来重新排列列表中的数字。我想知道如何根据对的数量来分离对(例如,如果对是 2,则分离数是 2)

如何对数字列表进行分隔和模式?


    package main

    import "fmt"

    func MagicPairs(list []int) {
        //length := len(list) * 2
        magicPair := []int{}
        magicPair = append(list, list...)

        for i := 0; i <len(magicPair); i++{
            if len(magicPair) == 0 {
                //do nothing
            }else{  
                m := max(list)
                for p, x := range magicPair{
                    if magicPair[len(magicPair)-1] == m {   
                        magicPair = append([]int{m}, (magicPair)[:len(magicPair)-1]...)
                        fmt.Println(magicPair)
                        return
                    }
                    if x == m{
                        magicPair = append([]int{m}, append((magicPair)[:p], (magicPair)[p+1:]...)...)
                    }

                    previousPair := magicPair[x]
                    if x == previousPair{

                    }

                }
            }
        }
        fmt.Println("1", magicPair)
    }

    func max(list[] int) int{
        max := list[0]
        for _, value := range list{
            if value > max {
                max = value 
            }
        }
        return max
    }

    func main(){
        list := [] int {0,1,2,3,4,5,6,7,8}
        MagicPairs(list)

    }

【问题讨论】:

标签: algorithm go pattern-matching


【解决方案1】:

您似乎试图通过将源列表加倍然后通过反复切片和连接数组来打乱数字来找到最佳解决方案。

我认为这个问题适用于递归方法。使用 2 * len(list) 空槽创建 thze 目标数组。 (槽位是否为空必须用特殊值标记,例如-1。)然后递归地尝试将原始数组的元素放入目标数组中。

让我们看看您的示例 {0, 1, 3}。创建目标数组:

. . . . . .

为0尝试所有可能的位置。第一个是

0 0 . . . .

现在尝试拟合 1. 有两种可能性

0 0 . . . .
0 0 1 . 1 .

但这不会容纳下一个元素,3. 后退一步:

0 0 . . . .
0 0 . 1 . 1

3 也不适合这里。我们已经用尽了对那个零位置的搜索,所以让我们寻找下一个可行的零位置:

. 0 0 . . .

只有一种放置方法:

. 0 0 . . .
. 0 0 1 . 1

现在让我们尝试拟合 3 并且,宾果游戏!,它符合:

. 0 0 . . .
. 0 0 1 . 1
3 0 0 1 3 1

现在您可以停止搜索或尝试寻找其他解决方案。在这种情况下,只有另一种解决方案,即这个解决方案的反射,但是有 300 种方法来放置从 1 到 8 的数字,例如。

这种方法几乎是蛮力的,但在实践中,填充数组的有效方法并不多,因此可以及早检测到错误的路径。也许将大数字放在首位会带来更好的性能。您可以使用它并对其进行测量。

这是一个可以做到这一点的程序。 (它可能看起来更像 C 而不是 Go。没关系。)

package main

import "fmt"

func fit_r(res[] int, a[] int, i int) int {
    n := len(a);

    if i == n {
        fmt.Printf("%v\n", res);
        return 1;
    } else {
        count := 0;
        m := a[i];

        for j := 0; j < 2*n - 1 - m; j++ {
            if res[j] == -1 && res[j + 1 + m] == -1 {
                // place values
                res[j] = m;
                res[j + 1 + m] = m;

                // test further values
                count += fit_r(res, a, i + 1);

                // clean up and remove values again
                res[j] = -1;
                res[j + 1 + m] = -1;
            }
        }        

        return count;
    }
}

func fit(a[] int) int {
    res := make([] int, 2 * len(a));

    for i := range res {
        res[i] = -1;
    }

    return fit_r(res, a, 0);
}

func main() {
    list := [] int {0, 1, 2, 3};
    n := fit(list);

    fmt.Println(n, "solutions");
}

【讨论】:

  • 非常感谢您的这些!!有用!这正是我一直在寻找的东西,我一直在为此苦苦挣扎。我真的很感激帮助。但是我可以知道为什么是 res[j + 1 + m] 和 j
  • 你总是放置一个距离为m的“魔术”对,其中j是左边数字的位置,j + 1 + m是右边数字的位置。正确的数字不能超出2*n 的数组边界,因此是循环条件j &lt; 2*n - 1 - m
  • 哦,好吧!我现在完全明白了。非常感谢!我可以知道这个解决方案的 O 表示法/性能可能是什么吗?是 O(n)^2 吗?由两个 for 循环派生?
  • 好问题。上限肯定是 O(n²),您可以通过像 {0, 0, 0} 这样的输入来获得它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
相关资源
最近更新 更多