使用场景问题:
查找集合 set :=[]int{1,2,3,4}中所有包含3的子集
思路:
1.包含3的子集有{3},{1,3},{2,3},{3,4},{1,2,3},{1,3,4},{2,3,4},{1,2,3,4} 共有8个
2.set集合的子集有: 2^(n-1)个,n表示集合元素个数
3.通过位置转换的方式,定义每个元素在集合中的位置 1-1位置 2-2位置 3-3位置 4-4位置
4.我们将位置转换为二进制, 用1表示元素对应在二进制的位置;如 1-0001 2-0010 3-0100 4-1000
5.我们将子集的个数0到2^(n-1)转换成二进制子集 子集对应二进制 二进制对应集合位置的数据 0 0000 {} 1 0001 {1} 2 0010 {2} 3 0011 {1,2} 4 0100 {3} 5 0101 {1,3} 6 0111 {1,2,3} . .... .... 15 1111 {1,2,3,4}
6.使用查找元素位置与位置子集进行与运算, 如果等于查找位置,则该子集位置包含了该查找元素
1.使用二进制存储状态到数据库字段, 现需要进行查询
2.查找一个类型商品的全部组合形式
1.查找指定元素位置的代码
// 查询需要查询元素的位置对应的二进制 转换后的十进制数
// 入参: 需要查询的数 如:3
// 找出3在集合中的位置, 0100
func findSubLoc(set []int,f int) int{
targetLoc := 0
for k,v := range set {
if v == f {
targetLoc = 1 << (k)
break
}
} return targetLoc
}
2.查询集合的子集个数
// 查询集合位置的所有子集
func findAllSubLocLen(set []int) int {
// 将集合拆分为子集应有 2^(集合长度-1) 个子集
setLen,_ := strconv.ParseFloat(fmt.Sprintf("%d", len(set)), 64)
subLen := int(math.Pow(2.0, setLen))
return subLen
}
3.将子集转换为集合中的元素
// 入参: 5
// 结果: [1,3]
func obToSlice(d int) []int {
res := make([]int, 0)
i := 1
flag := true
for flag {
if d == 0 {
flag = false
break
}
if d & 1 != 0 {
res = append(res, i)
} i++
d = d >> 1
}
return res
}
4.使用
func main() {
// 初始化集合
set := []int{1,2,3,4}
// 包含有3的所有子集
// 计算3的位置
targetLoc := findSubLoc(set, 3)
fmt.Printf("targetLoc:%d,%08b\n",targetLoc,targetLoc)
// 将集合拆分为子集应有 2^(集合长度-1) 个子集
n := findAllSubLocLen(set)
// 记录位置子集
subLoc := make([]int, 0)
// 打印出子集
for i := 0;i < n;i++{
// 如果查找位置与位置子集相与为查找位置, 则记录该子集
if targetLoc & i == targetLoc {
fmt.Printf("%08b,%08b\n",targetLoc,i)
subLoc = append(subLoc, i)
} } fmt.Printf("subLoc:%d, %08b\n",subLoc, subLoc)
// 将子集转换为集合数据
for _,v := range subLoc {
fmt.Println(obToSlice(v))
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)