题目:
给你一个二维整数数组 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
}