LeetCode 每日一题 2026/10/12-2026/10/18

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


目录

      • [10/12 2897. 对数组执行操作使平方和最大](#10/12 2897. 对数组执行操作使平方和最大)
      • [10/13 3727. 最大交替平方和](#10/13 3727. 最大交替平方和)
      • [10/14 3723. 数位平方和的最大值](#10/14 3723. 数位平方和的最大值)
      • [10/15 2913. 子数组不同元素数目的平方和 I](#10/15 2913. 子数组不同元素数目的平方和 I)
      • [10/16 2916. 子数组不同元素数目的平方和 II](#10/16 2916. 子数组不同元素数目的平方和 II)
      • [10/17 3551. 数位和排序需要的最小交换次数](#10/17 3551. 数位和排序需要的最小交换次数)
      • 10/18

10/12 2897. 对数组执行操作使平方和最大

AND/OR 操作不会增加或减少某一位上 1 的总数,只会把某个数的 1 挪到另一个数上。

平方和要最大,应该把 1 尽量集中到少数几个大数上,因为把一位从小数挪到大数,平方和会变大。

先统计每一位上有多少个 1,再贪心拼出 k 个数:每次把还没用完的位都放进当前这个数,让它尽量大,然后把平方加进答案。

python 复制代码
def maxSum(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """
    mod = 10**9 + 7
    cnt = [0] * 31
    for x in nums:
        for i in range(31):
            if x >> i & 1:
                cnt[i] += 1
    ans = 0
    for _ in range(k):
        x = 0
        for i in range(31):
            if cnt[i]:
                x |= 1 << i
                cnt[i] -= 1
        ans = (ans + x * x) % mod
    return ans

10/13 3727. 最大交替平方和

偶数位取正、奇数位取负,平方只和绝对值有关。

将绝对值大的放到偶数位,绝对值小的放到奇数位。

先取绝对值排序,较小的一半减去平方,较大的一半加上平方。

python 复制代码
def maxAlternatingSum(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    ans=0
    n=len(nums)
    l = [abs(x) for x in nums]
    l.sort()
    for i in range(n):
        if i<n//2:
            ans-=l[i]**2
        else:
            ans+=l[i]**2
    return ans

10/14 3723. 数位平方和的最大值

要凑恰好 num 位、数位和恰好是 sum 的数,让各位数字的平方和最大;平方和一样时取数值最大的那个。

平方和固定时数字越集中越大,所以尽量多用 9,剩下不足 9 的部分单独放一位。

同分时要数值最大,就把这些 9 放在最高位,余数紧跟其后,剩下的位补 0。

如果 sum 比 9*num 还大,凑不出来,返回空串。

python 复制代码
def maxSumOfSquares(num, sum):
    """
    :type num: int
    :type sum: int
    :rtype: str
    """
    if num * 9 < sum:
        return ""
    k, s = divmod(sum, 9)
    ans = "9" * k
    if s:
        ans += str(s)
    return ans + "0" * (num - len(ans))

10/15 2913. 子数组不同元素数目的平方和 I

每个子数组都要算一次「里面有多少个不同的数」,再把这个数平方后全部加起来。

数组很短,枚举左端点,再从左往右把右端点一格一格延长。

用集合记下当前这段出现过的数,集合大小就是不同元素个数,平方后加进答案。

python 复制代码
def sumCounts(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    n = len(nums)
    ans = 0
    for i in range(n):
        seen = set()
        for j in range(i, n):
            seen.add(nums[j])
            ans += len(seen) * len(seen)
    return ans

10/16 2916. 子数组不同元素数目的平方和 II

还是把每个子数组的不同元素个数平方后加起来,但数组很长,不能一段段枚举。

固定右端点从左往右扫,记下每个左端点到当前右端点这段里有多少个不同的数。

新来的数只对「上次出现位置之后」的那些左端点是新元素,这些段的不同个数都加 1。

一段数每个都加 1 时,平方和增加 2×原来的和 + 这段长度。用线段树做区间加 1 并维护平方和,每扫完一个右端点就加进答案,最后对 10^9+7 取模。

python 复制代码
def sumCounts(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    mod = 10**9 + 7
    n = len(nums)
    sm = [0] * (4 * n)
    sq = [0] * (4 * n)
    lz = [0] * (4 * n)

    def apply(p, l, r, v):
        length = r - l + 1
        sq[p] = (sq[p] + 2 * v * sm[p] + v * v * length) % mod
        sm[p] = (sm[p] + v * length) % mod
        lz[p] += v

    def push(p, l, r):
        if lz[p] and l < r:
            m = (l + r) // 2
            apply(p * 2, l, m, lz[p])
            apply(p * 2 + 1, m + 1, r, lz[p])
            lz[p] = 0

    def update(p, l, r, ql, qr):
        if ql <= l and r <= qr:
            apply(p, l, r, 1)
            return
        push(p, l, r)
        m = (l + r) // 2
        if ql <= m:
            update(p * 2, l, m, ql, qr)
        if qr > m:
            update(p * 2 + 1, m + 1, r, ql, qr)
        sm[p] = (sm[p * 2] + sm[p * 2 + 1]) % mod
        sq[p] = (sq[p * 2] + sq[p * 2 + 1]) % mod

    last = {}
    ans = 0
    for r, x in enumerate(nums):
        update(1, 0, n - 1, last.get(x, -1) + 1, r)
        last[x] = r
        ans = (ans + sq[1]) % mod
    return ans

10/17 3551. 数位和排序需要的最小交换次数

数位和更小的排前面,数位和相同则数字更小的排前面。

先按这个规则排出目标顺序,再看每个数现在在哪、应该去哪。

这些「当前位置指向目标位置」会连成若干个圈。一个圈里有 k 个数,最少交换 k-1 次就能各归其位,总次数就是 n 减去圈的个数。

python 复制代码
def minSwaps(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    def digit_sum(x):
        s = 0
        while x:
            s += x % 10
            x //= 10
        return s

    n = len(nums)
    order = sorted((digit_sum(x), x) for x in nums)
    pos = {x: i for i, (_, x) in enumerate(order)}
    vis = [False] * n
    ans = n
    for i in range(n):
        if vis[i]:
            continue
        ans -= 1
        j = i
        while not vis[j]:
            vis[j] = True
            j = pos[nums[j]]
    return ans

10/18

python 复制代码

相关推荐
青岚_Nox1 小时前
# C语言实战:函数完全指南——从基础概念到static/extern深度解析
算法
CCCCCCCCharlie1 小时前
深入解析I/O底层:文件描述符与缓冲区真相
linux·开发语言·c++·算法
Cccp.1231 小时前
【leetcode】(十三)大数据处理
数据结构·算法·leetcode
学逆向的1 小时前
C 选择结构的执行效率分析
c语言·开发语言·算法·网络安全
wzdark2 小时前
动态规划算法的状态转移矩阵可视化分析5
算法·矩阵·动态规划
Pniubi2 小时前
力扣70爬楼梯
数据结构·算法·leetcode
人工智能培训2 小时前
具身智能环境交互与学习范式原理
大数据·linux·人工智能·学习·算法·机器学习
纪念 2292 小时前
C++算法(三)
开发语言·c++·算法
学不会pwn不改名3 小时前
时间复杂度与空间复杂度详解
算法