1893. 检查是否区域内所有整数都被覆盖

78 阅读1分钟

题目:
给你一个二维整数数组 ranges 和两个整数 left 和 right 。每个 ranges[i] = [starti, endi] 表示一个从 starti 到 endi 的 闭区间 。

如果闭区间 [left, right] 内每个整数都被 ranges 中 至少一个 区间覆盖,那么请你返回 true ,否则返回 false 。

已知区间 ranges[i] = [starti, endi] ,如果整数 x 满足 starti <= x <= endi ,那么我们称整数x 被覆盖了。

算法:
方法一:差分数组
适用于不修改原始数组,多次区级查询

func isCovered(ranges [][]int, left int, right int) bool {
    diff := make([]int, 52)
    for i := range ranges {
        x, y := ranges[i][0], ranges[i][1]
        diff[x] = diff[x] + 1
        diff[y + 1] = diff[y + 1] - 1
    }

    sum := 0
    for i := 1; i <= 50; i ++ {
        sum = sum + diff[i]
        if left <= i && i <= right && sum <= 0{
            return false
        }
    }
    return true
}

方法二:树状数组
适用于多次单点修改,多次区间查询

func isCovered(ranges [][]int, left int, right int) bool {
    maxN := 52
    BIT = make([]int, maxN)

    // 构造BIT
    for i := range ranges {
        x, y := ranges[i][0], ranges[i][1]
        for j := x; j <= y; j ++ {
            Add(j, 1)
        }
    }
    // 检查[left, right]的每一位都有数存在
    for i := left; i <= right; i ++ {
        if Query(i) - Query(i - 1) == 0 {
            return false
        }
    }
    return true
}

var BIT []int
func Add(index, val int) {
    for i := index; i < len(BIT); i = i + lowbit(i) {
        BIT[i] = BIT[i] + val
    }
}

func Query(index int) int {
    sum := 0
    for i := index; i > 0; i = i - lowbit(i) {
        sum = BIT[i] + sum
    }
    return sum
}

func lowbit(x int) int {
    return x & -x
}

方法三:树状数组(点去重)
我们不能通过检查区间和来验证区间的每一个位置都被覆盖,是因为可能存在某个位置有多个覆盖次数,于是我们可以对重复覆盖的点进行去重。

func isCovered(ranges [][]int, left int, right int) bool {
    maxN := 52
    BIT = make([]int, maxN)
    coverd := make(map[int]bool)
    // 构造BIT
    for i := range ranges {
        x, y := ranges[i][0], ranges[i][1]
        for j := x; j <= y; j ++ {
            if !coverd[j] {
                Add(j, 1)
                coverd[j] = true
            }
            
        }
    }
    // 检查[left, right]的每一位都有数存在
    
    return Query(right) - Query(left - 1) == (right - left + 1)
}

var BIT []int
func Add(index, val int) {
    for i := index; i < len(BIT); i = i + lowbit(i) {
        BIT[i] = BIT[i] + val
    }
}

func Query(index int) int {
    sum := 0
    for i := index; i > 0; i = i - lowbit(i) {
        sum = BIT[i] + sum
    }
    return sum
}

func lowbit(x int) int {
    return x & -x
}

方法四:线段树
适用多次区间修改,多次区间查询

func isCovered(ranges [][]int, left int, right int) bool {
    N := 51
    ST = make([]*Node, 4 * N)
    Build(1, 1, N)
    for i := range ranges {
        for j := ranges[i][0]; j <= ranges[i][1]; j ++ {
            Update(1, j, 1)
        }
        
    }
    a := Query(1, left, right)
    return  a == (right - left + 1)
}

type Node struct {
    left, right int
    add, value int
}
var ST []*Node

func NewNode(left, right, value int) *Node {
    return &Node{
        left: left,
        right: right,
        value: value,
    }
}

// 不涉及动态开点,所有节点一次性建好了
func Build(node, left, right int) {
    if ST[node] == nil {
        ST[node] = NewNode(left, right, 0)
    }
    if left == right {
        return 
    }
    mid := (left + right) >> 1
    Build(node * 2, left, mid)
    Build(node * 2 + 1, mid + 1, right)
}

func Update(node, index, value int) {
    if index == ST[node].left && ST[node].right == index {
        ST[node].value = value 
        return
    }

    mid := (ST[node].left + ST[node].right) >> 1
    if index <= mid {
        Update(2 * node, index, 1)
    } else {
        Update(2 * node + 1, index, 1)
    }
    ST[node].value = ST[2 * node].value + ST[2 * node + 1].value 
}

func Query(node, left, right int) int {
    if left <= ST[node].left && ST[node].right <= right {
        return ST[node].value
    }
    mid := (ST[node].left + ST[node].right) >> 1
    ans := 0
    if left <= mid {
        ans = ans + Query(node * 2, left, right)
    } 
    if mid < right {
        ans = ans + Query(node * 2 + 1, left, right)
    }
    return ans
}