LeetCode 每日一题 2026/6/8-2026/6/14

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步


目录

      • [6/8 2161. 根据给定数字划分数组](#6/8 2161. 根据给定数字划分数组)
      • [6/9 3689. 最大子数组总值 I](#6/9 3689. 最大子数组总值 I)
      • [6/10 3691. 最大子数组总值 II](#6/10 3691. 最大子数组总值 II)
      • [6/11 3558. 给边赋权值的方案数 I](#6/11 3558. 给边赋权值的方案数 I)
      • [6/12 3559. 给边赋权值的方案数 II](#6/12 3559. 给边赋权值的方案数 II)
      • 6/13
      • 6/14

6/8 2161. 根据给定数字划分数组

按题意,结果数组要分成三段:

所有小于 pivot 的元素

所有等于 pivot 的元素

所有大于 pivot 的元素

并且每一段内部要保持原数组中的相对顺序,所以可直接一次遍历分类收集到三个列表

最后返回 less + equal + greater 即可

python 复制代码
def pivotArray(nums, pivot):
    """
    :type nums: List[int]
    :type pivot: int
    :rtype: List[int]
    """
    less = []
    equal = []
    greater = []

    for x in nums:
        if x < pivot:
            less.append(x)
        elif x == pivot:
            equal.append(x)
        else:
            greater.append(x)

    return less + equal + greater

6/9 3689. 最大子数组总值 I

相同子数组可以被选择超过一次

即找最大的一个子数组即可

找到最大值 最小值 他们在的子数组值最大

python 复制代码
def maxTotalValue(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """
    return (max(nums)-min(nums))*k

6/10 3691. 最大子数组总值 II

稀疏表 + 最大堆,多路归并

固定左端点 l,子数组值 f_l® = max(numsl...r) - min(numsl...r)。

当 r 向右扩展时,区间最大值只会不降、最小值只会不升,

所以 f_l® 单调不减。

因此对每个 l 而言,按 r = n-1, n-2, ..., l 的顺序看,

对应值是一个"非增序列"。问题变成:从 n 个非增序列里取前 k 大元素求和。

用最大堆做多路归并:

每个 l 先把 (l, n-1) 入堆(即该序列当前最大值)

每次弹出全局最大 (l, r),把它计入答案

再把同一序列的下一个元素 (l, r-1) 入堆(若 r-1 >= l)

关键是快速求任意区间 max/min:用 Sparse Table 预处理

python 复制代码
def maxTotalValue(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """
    import heapq

    n = len(nums)
    if n == 0 or k == 0:
        return 0

    log2 = [0] * (n + 1)
    for i in range(2, n + 1):
        log2[i] = log2[i // 2] + 1

    max_level = log2[n]

    # st_max[j][i] 表示区间 [i, i + 2^j - 1] 的最大值
    # st_min[j][i] 表示区间 [i, i + 2^j - 1] 的最小值
    st_max = [nums[:]]
    st_min = [nums[:]]

    j = 1
    while j <= max_level:
        length = 1 << j
        half = length >> 1
        size = n - length + 1

        prev_max = st_max[j - 1]
        prev_min = st_min[j - 1]
        cur_max = [0] * size
        cur_min = [0] * size

        for i in range(size):
            left_max = prev_max[i]
            right_max = prev_max[i + half]
            cur_max[i] = left_max if left_max >= right_max else right_max

            left_min = prev_min[i]
            right_min = prev_min[i + half]
            cur_min[i] = left_min if left_min <= right_min else right_min

        st_max.append(cur_max)
        st_min.append(cur_min)
        j += 1

    def range_value(l, r):
        """返回子数组 nums[l..r] 的值 = max - min。"""
        p = log2[r - l + 1]
        seg_len = 1 << p
        max_val = st_max[p][l]
        other_max = st_max[p][r - seg_len + 1]
        if other_max > max_val:
            max_val = other_max

        min_val = st_min[p][l]
        other_min = st_min[p][r - seg_len + 1]
        if other_min < min_val:
            min_val = other_min

        return max_val - min_val

    # 最大堆
    heap = []
    right = n - 1
    for left in range(n):
        heapq.heappush(heap, (-range_value(left, right), left, right))

    ans = 0
    for _ in range(k):
        neg_val, left, right = heapq.heappop(heap)
        ans -= neg_val

        # 同一左端点序列的下一个候选 (left, right-1)
        if right - 1 >= left:
            nxt_r = right - 1
            heapq.heappush(heap, (-range_value(left, nxt_r), left, nxt_r))

    return ans

6/11 3558. 给边赋权值的方案数 I

只关心从根节点 1 到"某个最深节点 x"的那条路径,其他边可忽略。

设该路径有 d 条边(即最大深度为 d)。

每条边权只能取 1 或 2,路径总和奇偶性只由"取 1 的条数"决定:

加 1 会翻转奇偶

加 2 不改变奇偶

因此问题变成:长度为 d 的位置上,每个位置选 1/2,有多少种方案让总和为奇数?

等价于"选奇数个位置放 1",组合恒等式可得方案数为 2^(d-1)。

所以只需求树的最大深度 d,然后返回 pow(2, d-1, MOD)。

python 复制代码
def assignEdgeWeights(edges):
    """
    :type edges: List[List[int]]
    :rtype: int
    """
    from collections import deque

    MOD = 10**9 + 7
    n = len(edges) + 1

    # 邻接表建树
    g = [[] for _ in range(n + 1)]
    for u, v in edges:
        g[u].append(v)
        g[v].append(u)

    # BFS 求从根 1 出发的最大深度(按"边数"计)
    q = deque([(1, 0, 0)])  # (node, parent, depth)
    max_depth = 0
    while q:
        cur, parent, depth = q.popleft()
        if depth > max_depth:
            max_depth = depth
        for nxt in g[cur]:
            if nxt != parent:
                q.append((nxt, cur, depth + 1))

    # d >= 1(题目 n >= 2),返回 2^(d-1) % MOD
    return pow(2, max_depth - 1, MOD)

6/12 3559. 给边赋权值的方案数 II

对单次查询 u, v,设路径边数为 d。

每条边可赋值 1 或 2,路径和奇偶性只取决于"有多少条边取 1":

加 1 会翻转奇偶

加 2 不改变奇偶

因此可行方案数 = 在 d 条边里选奇数条放 1 的方案数 = 2^(d-1)(d=0 时为 0)。

用 LCA(最近公共祖先)倍增预处理:

先 BFS 求每个点深度 depth 和其 2^j 级祖先 upjx

每次查询 O(log n) 求 lca(u, v)

距离 d = depthu + depthv - 2*depthlca

最终答案:

d == 0 -> 0

d > 0 -> pow(2, d-1, MOD)

python 复制代码
def assignEdgeWeights(edges, queries):
    """
    :type edges: List[List[int]]
    :type queries: List[List[int]]
    :rtype: List[int]
    """
    from collections import deque

    MOD = 10**9 + 7
    n = len(edges) + 1
    log = n.bit_length()

    # 建图
    g = [[] for _ in range(n + 1)]
    for u, v in edges:
        g[u].append(v)
        g[v].append(u)

    # up[j][x]: 节点 x 的 2^j 级祖先(0 表示不存在)
    up = [[0] * (n + 1) for _ in range(log)]
    depth = [0] * (n + 1)

    # BFS 预处理 depth 和 up[0]
    q = deque([1])
    parent = [0] * (n + 1)
    parent[1] = 0
    while q:
        x = q.popleft()
        for y in g[x]:
            if y == parent[x]:
                continue
            parent[y] = x
            depth[y] = depth[x] + 1
            up[0][y] = x
            q.append(y)

    # 倍增表
    for j in range(1, log):
        prev = up[j - 1]
        cur = up[j]
        for x in range(1, n + 1):
            mid = prev[x]
            cur[x] = prev[mid] if mid else 0

    def lca(a, b):
        if depth[a] < depth[b]:
            a, b = b, a

        # 先把 a 提升到与 b 同深度
        diff = depth[a] - depth[b]
        bit = 0
        while diff:
            if diff & 1:
                a = up[bit][a]
            diff >>= 1
            bit += 1

        if a == b:
            return a

        # 同时向上跳,找到 LCA 的下一层
        for j in range(log - 1, -1, -1):
            if up[j][a] != up[j][b]:
                a = up[j][a]
                b = up[j][b]
        return up[0][a]

    ans = []
    for u, v in queries:
        p = lca(u, v)
        d = depth[u] + depth[v] - 2 * depth[p]
        if d == 0:
            ans.append(0)
        else:
            ans.append(pow(2, d - 1, MOD))
    return ans

6/13

python 复制代码

6/14

python 复制代码

相关推荐
鱼子星_1 小时前
【数据结构】排序的拓展——快速排序的生态多样性与归并排序沾染文件操作
c语言·数据结构·算法
KaMeidebaby1 小时前
卡梅德生物技术快报|噬菌体展示文库构建全流程解析 | 大豆球蛋白纳米抗体筛选实践
人工智能·python·tcp/ip·算法·机器学习
CC数学建模1 小时前
2026年第十六届APMCM 亚太地区大学生数学建模竞赛(中文赛项)赛题B题:高性能芯片热管理系统的优化问题完整思路、代码、模型、文章,全网首发高质量分享!
python·算法·数学建模
爱睡懒觉的焦糖玛奇朵1 小时前
【视觉检测之人员奔跑检测算法开发思路】
人工智能·python·深度学习·算法·yolo·视觉检测
05候补工程师2 小时前
【408考研复习】数据结构核心笔记:字符串模式匹配与内部排序算法全解析
数据结构·经验分享·笔记·考研·算法·排序算法
阿文的代码库2 小时前
浅谈:无向图的欧拉回路
算法
-Thinker2 小时前
AI 算法核心原理与实现
人工智能·算法·机器学习
Eloudy2 小时前
最小权重完美匹配(MWPM)与表面码纠错
算法·量子计算
-森屿安年-2 小时前
62. 不同路径
算法·动态规划