【笔试刷题】阿里系列-2026.04.15-算法岗-改编真题

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🤖 内容包含AI辅助生成,题解和代码均经过多轮验证,有问题欢迎评论

🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的

春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗

阿里系列-2026.04.15-算法岗

题目总览

题号 题名 主要做法 难度
1 账本翻转收益 构造 + 奇偶分析 中等
2 真假记录带 线性 DP 中等
3 并色时刻查询 线段树 / 区间最大值 困难

这套阿里算法岗前两题看着不长,但都要先把等价转化想清楚。第一题是翻转可达性,第二题是窗口限制改写成间距限制,第三题再把整段染色过程压成边界删除时刻查询。

1. 小兰的账本翻转收益

问题描述

说明:阿里系列近期多条业务线笔试题基本共用同一套公开机试,淘天、阿里云等方向都可参考本场。

小兰在整理一份长度为 的收支账本,第 项的数值为 ,正数表示收益,负数表示亏损。

她可以进行若干次操作,也可以一次都不做。每次操作选择一个下标 ,其中 ,然后把相邻两项 同时取反。

也就是说,这次操作会执行:

请计算,经过若干次操作后,整个账本元素之和的最大值。

输入格式

每个测试文件都包含多组测试数据。

  • 第一行输入一个整数 ,表示数据组数。
  • 对于每组数据:
  • 第一行输入一个整数 ,表示数组长度。
  • 第二行输入 个整数 ,表示账本中的各项数值。

保证所有测试数据中 的总和不超过

输出格式

对于每组数据输出一行一个整数,表示能够得到的最大元素和。

样例输入

2
4
-1 -3 2 4
3
-5 2 1

样例输出

10
6

数据范围

  • 所有测试数据中 的总和不超过

样例说明

  • 样例 1:第一组把前两个负数一起翻成正数后,总和变成 。第二组由于只能成对翻转,最优结果是

题解

先看一次操作真正改变了什么

每次操作会把一对相邻位置同时取反。

如果把位置是否“被翻转奇数次”单独拿出来看,会发现一次操作只会让两个位置的状态发生变化。所以无论执行多少次,最终被翻转奇数次的位置数量一定是偶数个。

这个结论不只是必要条件,而且也是充分条件。

假设想让位置 和位置 的符号发生变化,其中 。只要依次对:

这些下标各做一次操作,那么中间位置都会被翻转两次,只有两端位置各翻转一次。

于是:

  • 可以只翻转任意一对位置。
  • 继续把多组这样的“成对翻转”拼起来,就能翻转任意一个偶数大小的位置集合。

所以,题目等价于:

  • 可以把任意偶数个元素改成相反数;
  • 目标是让最终元素和尽量大。

最大值只和负数个数的奇偶性有关

设:

  • 表示所有元素绝对值之和;
  • 表示原数组里负数的个数;
  • 表示所有元素绝对值中的最小值。

如果 是偶数,那么可以把所有负数全部翻成正数,最后答案就是:

如果 是奇数,那么最终仍然必须保留奇数个负数,因为一次操作只会同时改变两个位置的符号,不会改变负数个数的奇偶性。

这时最优策略就是让绝对值最小的那个数保留负号,其余都变成正数。这样损失最小,答案就是:

注意如果数组里有 ,那么 ,公式仍然成立,此时答案就是

复杂度分析

每组数据只需要扫一遍数组:

  • 统计绝对值总和;
  • 统计负数个数;
  • 维护最小绝对值。

所以单组时间复杂度是 ,额外空间复杂度是

参考代码(Python)

import sys

input = lambda: sys.stdin.readline().strip()


def solve() -> None:
    # Read input in ACM mode and build the answer directly.
    t = int(input())
    out = []

    for _ in range(t):
        n = int(input())
        arr = list(map(int, input().split()))

        sum_abs = 0
        cnt_neg = 0
        mn = 10**30

        for x in arr:
            # 逐个统计绝对值总和、负数个数和最小绝对值。
            if x < 0:
                cnt_neg += 1
            ax = abs(x)
            sum_abs += ax
            if ax < mn:
                mn = ax

        # 负数个数为奇数时,必须留下一个绝对值最小的负数。
        if cnt_neg % 2 == 1:
            sum_abs -= 2 * mn

        out.append(str(sum_abs))

    sys.stdout.write("\n".join(out))


if __name__ == "__main__":
    # Standard ACM entry.
    solve()

2. 园子的真假记录带

问题描述

说明:阿里系列近期多条业务线笔试题基本共用同一套公开机试,淘天、阿里云等方向都可参考本场。

园子 正在核对一串真假记录,一共有 个位置。

每个位置的取值只可能是:

  • 1,表示这一条记录为真;
  • 0,表示这一条记录为假;
  • -1,表示这一条记录还没有确定。

她还知道一个限制:任意连续的 条记录中,至多只能出现一条假记录。

现在需要把所有 -1 替换成 01,并且满足上面的限制。请计算一共有多少种不同的填充方案。

由于答案可能很大,请输出对 取模后的结果。

输入格式

每个测试文件都包含多组测试数据。

  • 第一行输入一个整数 ,表示数据组数。
  • 对于每组数据:
  • 第一行输入两个整数 ,表示记录总数和窗口长度。
  • 第二行输入 个整数 ,其中

保证给出的已知信息本身一定合法,也就是说,在所有已知的 0 中,不会提前出现违反条件的情况。

保证所有测试数据中 的总和不超过

输出格式

对于每组数据输出一行一个整数,表示合法填充方案数对 取模后的结果。

样例输入

3
5 2
-1 -1 -1 -1 -1
4 3
1 -1 0 -1
6 1
1 -1 -1 -1 -1 0

样例输出

13
1
16

数据范围

  • 所有测试数据中 的总和不超过

样例说明

  • 样例 1:第一组共有 种合法填法。第二组只有唯一可行方案。第三组中 ,四个未知位置都可以独立填写,所以答案是

题解

条件可以换成“任意两个假话至少隔 个位置”

题目说的是:

  • 任意长度为 的连续区间里,
  • 至多只有一个 0

把它换个角度来看,就是任意两个填成 0 的位置,距离不能小于

原因很直接:

  • 如果两个 0 的位置差小于 ,那么一定能找到一个长度为 的窗口,把它们同时包含进去;
  • 反过来,如果所有 0 两两之间的距离都至少是 ,那么任意长度为 的区间里就不可能出现两个 0

所以问题变成:

  • 哪些位置要放 0
  • 这些位置之间必须至少间隔
  • 已知为 1 的位置不能放 0
  • 已知为 0 的位置必须放 0

表示前 个位置的方案数

用 表示前 个位置已经填完,并且满足条件的方案

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

最喜欢秋天的火龙果很...:第一份工作一定要往大的去,工资低点没事。后面换工作会更好找,即使你去小公司,你也不可能不会换工作的。所以找大的去
点赞 评论 收藏
分享
04-13 09:56
已编辑
嵌入式工程师
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务