Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何确定范围列表是否涵盖给定范围?_Algorithm_Sorting_Go_Search - Fatal编程技术网

Algorithm 如何确定范围列表是否涵盖给定范围?

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{ 返

我想有效地确定范围列表是否覆盖给定范围。例如,范围列表[(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{
返回长度(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