Algorithm 如何确定范围列表是否涵盖给定范围?
我想有效地确定范围列表是否覆盖给定范围。例如,范围列表[(0-3)、(3-5)、(4-8)、(6-10)]涵盖范围(0-10),而[(5-10)、(0-3)]不涵盖范围。该列表可以包含重叠,并且不一定按顺序排列 我尝试实现一个如下所示的Algorithm 如何确定范围列表是否涵盖给定范围?,algorithm,sorting,go,search,Algorithm,Sorting,Go,Search,我想有效地确定范围列表是否覆盖给定范围。例如,范围列表[(0-3)、(3-5)、(4-8)、(6-10)]涵盖范围(0-10),而[(5-10)、(0-3)]不涵盖范围。该列表可以包含重叠,并且不一定按顺序排列 我尝试实现一个如下所示的Continuous函数,该函数检查字节范围片是否包含给定的start和end type byteRange结构{ 启动int64 结束int64 } 键入byteRanges[]*byteRange func(brs byteRanges)Len()int{ 返
Continuous
函数,该函数检查字节范围片是否包含给定的start
和end
type byteRange结构{
启动int64
结束int64
}
键入byteRanges[]*byteRange
func(brs byteRanges)Len()int{
返回长度(brs)
}
func(brs byteRanges)掉期(i,j int){
brs[i],brs[j]=brs[j],brs[i]
}
func(brs byteRanges)减去(i,j int)bool{
返回brs[i].startcurPos+1{
返回错误
}
如果curPos=结束{
返回真值
}
}
返回错误
}
该函数的行为正确,但在处理大量范围列表以及经常调用时,性能不是很好。有人能推荐一种算法/实现来加速这种逻辑吗?更简单的解决方案
package main
import (
"fmt"
"sort"
)
type byteRange struct {
start int64
end int64
}
type byteRanges []*byteRange
func (brs byteRanges) Continuous(start int64, end int64) bool {
sort.Slice(brs, func(i, j int) bool {
return brs[i].start < brs[j].start
})
var (
longestReach int64
in bool
)
for _, br := range brs {
if !in {
// first br satrts laying over the target
if br.start <= start && br.end >= start {
longestReach = br.end
in = true
}
continue
}
if in && longestReach < br.start-1 {
break
}
if longestReach < br.end {
longestReach = br.end
}
}
return in && longestReach >= end
}
func main() {
brs := byteRanges{{5, 9}, {6, 10}}
fmt.Println(brs.Continuous(8, 10))
}
主程序包
进口(
“fmt”
“排序”
)
类型byteRange结构{
启动int64
结束int64
}
键入byteRanges[]*byteRange
func(brs字节数)连续(起始int64,结束int64)布尔{
sort.Slice(brs,func(i,j int)bool{
返回brs[i].start=结束
}
func main(){
brs:=byteRanges{{5,9},{6,10}
fmt打印(brs连续(8,10))
}
更简单的解决方案
package main
import (
"fmt"
"sort"
)
type byteRange struct {
start int64
end int64
}
type byteRanges []*byteRange
func (brs byteRanges) Continuous(start int64, end int64) bool {
sort.Slice(brs, func(i, j int) bool {
return brs[i].start < brs[j].start
})
var (
longestReach int64
in bool
)
for _, br := range brs {
if !in {
// first br satrts laying over the target
if br.start <= start && br.end >= start {
longestReach = br.end
in = true
}
continue
}
if in && longestReach < br.start-1 {
break
}
if longestReach < br.end {
longestReach = br.end
}
}
return in && longestReach >= end
}
func main() {
brs := byteRanges{{5, 9}, {6, 10}}
fmt.Println(brs.Continuous(8, 10))
}
主程序包
进口(
“fmt”
“排序”
)
类型byteRange结构{
启动int64
结束int64
}
键入byteRanges[]*byteRange
func(brs字节数)连续(起始int64,结束int64)布尔{
sort.Slice(brs,func(i,j int)bool{
返回brs[i].start=结束
}
func main(){
brs:=byteRanges{{5,9},{6,10}
fmt打印(brs连续(8,10))
}
由于您将在同一组范围上重复调用Continuous
,因此最好创建一个concurate
方法(或您希望调用的任何方法),该方法将获取一个切片,并返回一个新切片,其中对范围进行排序,并合并所有重叠范围。对于任何给定的范围集,只需调用一次concurate
Continuous
然后可以要求仅对Concurate
的结果调用它。(为了强制执行此要求,最好让压缩
实际返回一个自定义类型的结构
,它只是一个片的包装器,并且只在该结构
类型上定义连续
。如果您想方便起见,您可以定义一个单独的连续
方法。)d,它可以直接在片上调用,调用压缩
,然后调用连续
。当然,这种方便的方法也会很慢,但对于只检查一次的集合来说可能很方便。)
concure
中的合并逻辑非常简单:
- 如果切片为空,只需返回它(提前退出)
- 按其
对范围进行排序开始
- 创建一个名为
的新切片result
- 将
初始化为第一个范围prevRange
- 在范围内迭代。每一项:
- 如果当前范围在
之后开始,请将prevRange.end+1
添加到prevRange
,然后将result
设置为当前范围prevRange
- 否则,如果当前范围在
之后结束,则将prevRange.end
设置为当前范围的prevRange.end
end
- 如果当前范围在
- 将
添加到prevRange
result
Continuous
中的逻辑现在可以是:
- 对这些范围执行二进制搜索,查找
小于或等于start
的最后一个范围start
- 如果此范围的
大于或等于end
,则返回end
;否则,返回true
false
Continuous
,因此最好创建一个concurate
方法(或您希望调用的任何方法),该方法将获取一个切片并返回一个新切片,其中对范围进行排序,并合并所有重叠范围。对于任何给定的范围集,只需调用一次concurate
Continuous
然后可以要求仅对Concurate
的结果调用它。(为了执行此要求,最好使用C