给出下面三个数字序列,我想知道如何对这些数字进行分组,以找到它们之间最密切的关系.

1,2,3,4
4,3,5
2,1,3
...

我不确定我要寻找的算法叫什么,但我们可以看到与一些数字的关系比与其他数字的关系更强.

这些数字同时出现两次:

1 & 2
1 & 3
2 & 3
3 & 4

在一起一次:

1 & 4
2 & 4
3 & 5
4 & 5

例如,我们可以看到1, 2, & 3之间一定有关系,因为它们至少一起出现两次.你也可以说3 & 4是密切相关的,因为它们也出现了两次.然而,算法可能会 Select [1,2,3](超过[3,4]),因为它是一个更大的分组(更具包容性).

如果我们将最常用的数字组合在一个组中,我们可以形成以下任何一组:

[1,2,3] & [4,5]
[1,2]   & [3,4]   & [5]
[1,2]   & [3,4,5]
[1,2]   & [3,4]   & [5]

如果允许重复,您甚至可能最终得到以下组:

[1,2,3,4] [1,2,3] [3,4] [5]

我不能说哪种分组最"正确",但这四种组合都找到了不同的方法来半正确地分组数字.我不是在寻找一个特定的分组——只是一个通用的聚类算法,它工作得相当好,易于理解.

我相信也有很多其他方法可以使用发生次数计数来对它们进行分组.对于这些,什么是好的基本分组算法?最好使用GO、Javascript或PHP格式的示例.

推荐答案

正如前面提到的,这是关于集团的.如果你想得到确切的答案,就会遇到最大团问题,这个问题是NP完全的.因此,只有当你的符号(数字)的字母表有合理的大小时,下面的所有内容才有意义.在这种情况下,伪码中最大团问题不是非常优化的算法

Function Main
    Cm ← ∅                   // the maximum clique
    Clique(∅,V)              // V vertices set
    return Cm
End function Main

Function Clique(set C, set P) // C the current clique, P candidat set
    if (|C| > |Cm|) then
        Cm ← C
    End if
    if (|C|+|P|>|Cm|)then
        for all p ∈ P in predetermined order, do
            P ← P \ {p}
            Cp ←C ∪ {p}
            Pp ←P ∩ N(p)        //N(p) set of the vertices adjacent to p
            Clique(Cp,Pp)
        End for
    End if
End function Clique

因为围棋是我 Select 的语言,所以这里是实现

package main

import (
    "bufio"
    "fmt"
    "sort"
    "strconv"
    "strings"
)

var adjmatrix map[int]map[int]int = make(map[int]map[int]int)
var Cm []int = make([]int, 0)
var frequency int


//For filter
type resoult [][]int
var res resoult
var filter map[int]bool = make(map[int]bool)
var bf int
//For filter


//That's for sorting
func (r resoult) Less(i, j int) bool {
    return len(r[i]) > len(r[j])
}

func (r resoult) Swap(i, j int) {
    r[i], r[j] = r[j], r[i]
}

func (r resoult) Len() int {
    return len(r)
}
//That's for sorting


//Work done here
func Clique(C []int, P map[int]bool) {
    if len(C) >= len(Cm) {

        Cm = make([]int, len(C))
        copy(Cm, C)
    }
    if len(C)+len(P) >= len(Cm) {
        for k, _ := range P {
            delete(P, k)
            Cp := make([]int, len(C)+1)
            copy(Cp, append(C, k))
            Pp := make(map[int]bool)
            for n, m := range adjmatrix[k] {
                _, ok := P[n]
                if ok && m >= frequency {
                    Pp[n] = true
                }
            }
            Clique(Cp, Pp)

            res = append(res, Cp)
            //Cleanup resoult
            bf := 0
            for _, v := range Cp {
                bf += 1 << uint(v)
            }
            _, ok := filter[bf]
            if !ok {
                filter[bf] = true
                res = append(res, Cp)
            }
            //Cleanup resoult
        }
    }
}
//Work done here

func main() {
    var toks []string
    var numbers []int
    var number int


//Input parsing
    StrReader := strings.NewReader(`1,2,3
4,3,5
4,1,6
4,2,7
4,1,7
2,1,3
5,1,2
3,6`)
    scanner := bufio.NewScanner(StrReader)
    for scanner.Scan() {
        toks = strings.Split(scanner.Text(), ",")
        numbers = []int{}
        for _, v := range toks {
            number, _ = strconv.Atoi(v)
            numbers = append(numbers, number)

        }
        for k, v := range numbers {
            for _, m := range numbers[k:] {
                _, ok := adjmatrix[v]
                if !ok {
                    adjmatrix[v] = make(map[int]int)
                }
                _, ok = adjmatrix[m]
                if !ok {
                    adjmatrix[m] = make(map[int]int)
                }
                if m != v {
                    adjmatrix[v][m]++
                    adjmatrix[m][v]++
                    if adjmatrix[v][m] > frequency {
                        frequency = adjmatrix[v][m]
                    }
                }

            }
        }
    }
    //Input parsing

    P1 := make(map[int]bool)


    //Iterating for frequency of appearance in group
    for ; frequency > 0; frequency-- {
        for k, _ := range adjmatrix {
            P1[k] = true
        }
        Cm = make([]int, 0)
        res = make(resoult, 0)
        Clique(make([]int, 0), P1)
        sort.Sort(res)
        fmt.Print(frequency, "x-times ", res, " ")
    }
    //Iterating for frequency of appearing together
}

在这里,你可以看到它是https://play.golang.org/p/ZiJfH4Q6GJ工作的,并且可以处理输入的数据.但同样,这种方法适用于合理大小的字母表(以及任何大小的输入数据).

Go相关问答推荐

向API网关终结点发出POST请求时出现AWS Lambda With Go:";Rune me.InvalidEntrypoint";错误

Pulumi-S3-当策略依赖于访问点时,如何将AccesspintPolicy附加到访问点

为什么Slices包中的函数定义Slice参数的类型参数?

创建使用逗号而不是加号分隔OU的CSR

无法在go中为docker容器写入有效的挂载路径

Opensearch 错误 ping 弹性服务器:由未知权威签署的 x509 证书

加密/椭圆:try 在无效点上进行操作

如何使用 go-git 将特定分支推送到远程

甚至用天真的洗牌分配?

使用图像解码 JPEG 时 colored颜色 不正确.解码并写入 PDF?

如何处理 Go 的 firebase admin sdk 错误?

从动态输入中提取字符串,其中部分字符串可能不存在

Golang grpc go.mod 问题

如何在 Golang 中使用具有相同名称或特定关键字的行或列重新排列/排序 CSV

通用函数与外部包中的常见成员一起处理不同的 struct ?

K8s 算子读取原始数据

使用正则表达式拆分具有相同标题的数据块

退格字符在围棋操场中不起作用

如何允许可转换为指针的泛型类型参数化另一种可转换为指针的泛型类型?

Golang 泛型同时具有接口和实现