LeetCode493周赛T3,前后缀分解

给你一个整数数组 nums。

如果子数组中相邻元素的差值是一个常数,那么这个子数组被称为 等差子数组。

你可以将 nums 中的 最多 一个元素替换为任意一个 整数。然后,从 nums 中选择一个等差子数组。

返回一个整数,该整数表示你可以选择的 最长 等差子数组的长度。

子数组 是数组中一段连续的元素序列。

示例 1:

输入: nums = 9,7,5,10,1

输出: 5

解释:

将 nums3 = 10 替换为 3,数组变为 9, 7, 5, 3, 1

选择子数组 9, 7, 5, 3, 1,它是等差数组,相邻元素的公差为 -2。

示例 2:

输入: nums = 1,2,6,7

输出: 3

解释:

将 nums0 = 1 替换为 -2,数组变为 -2, 2, 6, 7

选择子数组 -2, 2, 6, 7,它是等差数组,相邻元素的公差为 4。

提示:

4 <= nums.length <= 105

1 <= numsi <= 105

前后缀分解

  1. 可以在O(n)复杂度内计算出最长的等差长度
  2. 然后枚举每一个元素是否需要更改,更改了以后对前后序列的影响
  3. 一定要明白定义数组的含义,这题解法有好几个写法,原理不难,但是不同解法对应的下标不同,容易绕晕,我定义pre[i]表示以nums[i]为结尾的等差序列的最大长度,这是从前往后 算的;suf[i]表示以nums[i]结尾的等差序列的长度,是从后往前算
java 复制代码
class Solution {
    public int longestArithmetic(int[] nums) {
        int n = nums.length;
//        pre[i] 表示 nums[0..i] 中最长等差数列的长度
        int[] pre = new int[n];
        pre[0] = 1;
        pre[1] = 2;
        for (int i = 2; i < n; i++) {
            if (nums[i] - nums[i-1] == nums[i - 1] - nums[i - 2]) {
                pre[i] = pre[i - 1] + 1;
            } else {
                pre[i] = 2;
            }
        }
//        suf[i]表示 nums[i..n-1] 中最长等差数列的长度
        int[] suf = new int[n];
        suf[n-1] = 1;
        suf[n-2] = 2;
        for (int i = n-3; i >= 0; i --) {
            if (nums[i] - nums[i+1] == nums[i + 1] - nums[i + 2]) {
                suf[i] = suf[i + 1] + 1;
            } else {
                suf[i] = 2;
            }
        }
        int ans = 0;
        for (int x : pre) {
            ans = Math.max(ans, x);
        }
//        这里ans + 1为了处理更改的元素为端点
        ans ++;

        if (ans >= n) { // 整个数组是等差的,或者修改端点元素后是等差的
            return n;
        }
        for (int i = 1; i < n - 1; i++) {
            // 把 nums[i] 改成 d2 / 2
            int d2 = nums[i + 1] - nums[i - 1];
            if (d2 % 2 != 0) { // d2 / 2 必须是整数
                continue;
            }
//            如果修改过的元素与之前的元素是等差的
            boolean okLeft = i > 1 && nums[i - 1] - nums[i - 2] == d2 / 2;
            boolean okRight = i + 2 < n && nums[i + 2] - nums[i + 1] == d2 / 2;

//           suf[i+1]表示 nums[i+1..n-1] 中最长等差数列的长度
            if (okLeft && okRight) {
                ans = Math.max(ans, pre[i - 1] + 1 + suf[i + 1]);
            } else if (okLeft) {
//                +2 表示修改后的序列多加了nums[i].nums[i+1]
                ans = Math.max(ans, pre[i - 1] + 2);
            } else if (okRight) {
                ans = Math.max(ans, suf[i + 1] + 2);
            }
        }

        return ans;
    }



}
相关推荐
luj_17688 分钟前
毒素驱动的生物自毁机制探析
服务器·c语言·开发语言·经验分享·算法
一水鉴天21 分钟前
问题分类的三元组映射体系与求解方法论 20260901(千问)
人工智能·算法·机器学习
breeze jiang22 分钟前
LangChain Memory 实战:用 InMemoryChatMessageHistory 管理多轮对话
前端·算法·langchain
地平线开发者15 小时前
【模型轻量化专题】衡量模型轻量性的指标
算法
学习星球19 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
alphaTao1 天前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
Interview Aid1121 天前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
顶点多余1 天前
那些在算法中适合巩固的知识点---1
java·前端·算法
AI情绪识别开源1 天前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
罗西的思考1 天前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习