LeetCode 题解工作台
更新数组后处理求和查询
给你两个下标从 0 开始的数组 nums1 和 nums2 ,和一个二维数组 queries 表示一些操作。总共有 3 种类型的操作: 操作类型 1 为 queries[i] = [1, l, r] 。你需要将 nums1 从下标 l 到下标 r 的所有 0 反转成 1 并且所有 1 反转成 0 。…
2
题型
4
代码语言
3
相关题
当前训练重点
困难 · 数组·结合·segment·树
答案摘要
根据题目描述: - 操作 是把数组 `nums1` 的下标区间 的所有数反转,即把 变成 ,把 变成 。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 数组·结合·segment·树 题型思路
题目描述
给你两个下标从 0 开始的数组 nums1 和 nums2 ,和一个二维数组 queries 表示一些操作。总共有 3 种类型的操作:
- 操作类型 1 为
queries[i] = [1, l, r]。你需要将nums1从下标l到下标r的所有0反转成1并且所有1反转成0。l和r下标都从 0 开始。 - 操作类型 2 为
queries[i] = [2, p, 0]。对于0 <= i < n中的所有下标,令nums2[i] = nums2[i] + nums1[i] * p。 - 操作类型 3 为
queries[i] = [3, 0, 0]。求nums2中所有元素的和。
请你返回一个 数组,包含 所有第三种操作类型 的答案。
示例 1:
输入:nums1 = [1,0,1], nums2 = [0,0,0], queries = [[1,1,1],[2,1,0],[3,0,0]] 输出:[3] 解释:第一个操作后 nums1 变为 [1,1,1] 。第二个操作后,nums2 变成 [1,1,1] ,所以第三个操作的答案为 3 。所以返回 [3] 。
示例 2:
输入:nums1 = [1], nums2 = [5], queries = [[2,0,0],[3,0,0]] 输出:[5] 解释:第一个操作后,nums2 保持不变为 [5] ,所以第二个操作的答案是 5 。所以返回 [5] 。
提示:
1 <= nums1.length,nums2.length <= 105nums1.length = nums2.length1 <= queries.length <= 105queries[i].length = 30 <= l <= r <= nums1.length - 10 <= p <= 1060 <= nums1[i] <= 10 <= nums2[i] <= 109
解题思路
方法一:线段树
根据题目描述:
- 操作 是把数组
nums1的下标区间 的所有数反转,即把 变成 ,把 变成 。 - 操作 是求数组
nums2的所有数之和。 - 操作 是把数组
nums2的所有数之和加上 乘以数组nums1所有数之和,即 。
因此,我们实际上只需要维护数组 nums1 的区间和即可,我们可以通过线段树来实现。
我们定义线段树的每个节点为 Node,每个节点包含如下属性:
l:节点的左端点,下标从 开始。r:节点的右端点,下标从 开始。s:节点的区间和。lazy:节点的懒标记。
线段树主要有以下几个操作:
build(u, l, r):建立线段树。pushdown(u):下传懒标记。pushup(u):用子节点的信息更新父节点的信息。modify(u, l, r):修改区间和,本题中是反转区间中的每个数,那么区间和 。query(u, l, r):查询区间和。
我们先算出数组 nums2 的所有数之和,记为 。
执行操作 时,我们只需要调用 modify(1, l + 1, r + 1) 即可。
执行操作 时,我们更新 即可。
执行操作 时,我们只需要将 加入答案数组即可。
时间复杂度 ,空间复杂度 。其中 和 分别为数组 nums1 和 queries 的长度。
class Node:
def __init__(self):
self.l = self.r = 0
self.s = self.lazy = 0
class SegmentTree:
def __init__(self, nums):
self.nums = nums
n = len(nums)
self.tr = [Node() for _ in range(n << 2)]
self.build(1, 1, n)
def build(self, u, l, r):
self.tr[u].l, self.tr[u].r = l, r
if l == r:
self.tr[u].s = self.nums[l - 1]
return
mid = (l + r) >> 1
self.build(u << 1, l, mid)
self.build(u << 1 | 1, mid + 1, r)
self.pushup(u)
def modify(self, u, l, r):
if self.tr[u].l >= l and self.tr[u].r <= r:
self.tr[u].lazy ^= 1
self.tr[u].s = self.tr[u].r - self.tr[u].l + 1 - self.tr[u].s
return
self.pushdown(u)
mid = (self.tr[u].l + self.tr[u].r) >> 1
if l <= mid:
self.modify(u << 1, l, r)
if r > mid:
self.modify(u << 1 | 1, l, r)
self.pushup(u)
def query(self, u, l, r):
if self.tr[u].l >= l and self.tr[u].r <= r:
return self.tr[u].s
self.pushdown(u)
mid = (self.tr[u].l + self.tr[u].r) >> 1
res = 0
if l <= mid:
res += self.query(u << 1, l, r)
if r > mid:
res += self.query(u << 1 | 1, l, r)
return res
def pushup(self, u):
self.tr[u].s = self.tr[u << 1].s + self.tr[u << 1 | 1].s
def pushdown(self, u):
if self.tr[u].lazy:
mid = (self.tr[u].l + self.tr[u].r) >> 1
self.tr[u << 1].s = mid - self.tr[u].l + 1 - self.tr[u << 1].s
self.tr[u << 1].lazy ^= 1
self.tr[u << 1 | 1].s = self.tr[u].r - mid - self.tr[u << 1 | 1].s
self.tr[u << 1 | 1].lazy ^= 1
self.tr[u].lazy ^= 1
class Solution:
def handleQuery(
self, nums1: List[int], nums2: List[int], queries: List[List[int]]
) -> List[int]:
tree = SegmentTree(nums1)
s = sum(nums2)
ans = []
for op, a, b in queries:
if op == 1:
tree.modify(1, a + 1, b + 1)
elif op == 2:
s += a * tree.query(1, 1, len(nums1))
else:
ans.append(s)
return ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | complexity is O((n+q) log n) due to segment tree operations for range flips and sum queries, where n is array length and q is number of queries. Space complexity is O(n) for storing the segment tree and lazy markers. |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for candidates using naive iteration versus segment tree optimization.
- question_mark
Expect awareness of lazy propagation to handle large ranges efficiently.
- question_mark
Check understanding of combining array operations with segment tree updates.
常见陷阱
外企场景- error
Updating nums1 naively for every flip causes TLE on large inputs.
- error
Adding to nums2 without referencing the current nums1 ones count leads to incorrect results.
- error
Computing sum of nums2 from scratch each type 3 query is inefficient.
进阶变体
外企场景- arrow_right_alt
Compute prefix sums instead of using a segment tree for smaller constraints.
- arrow_right_alt
Handle multiple nums2 arrays updated simultaneously using the same nums1 flips.
- arrow_right_alt
Support dynamic length changes in nums1 and nums2 with additional insert/delete queries.