LeetCode493周赛T3,前后缀分解

给你一个整数数组 nums。

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

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

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

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

示例 1:

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

输出: 5

解释:

将 nums[3] = 10 替换为 3,数组变为 [9, 7, 5, 3, 1]。

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

示例 2:

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

输出: 3

解释:

将 nums[0] = 1 替换为 -2,数组变为 [-2, 2, 6, 7]。

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

提示:

4 <= nums.length <= 105

1 <= nums[i] <= 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;
    }



}
相关推荐
故事和你91几秒前
蓝桥杯-2025年C++B组国赛
开发语言·软件测试·数据结构·c++·算法·职场和发展·蓝桥杯
py有趣7 分钟前
力扣热门100题之合并区间
算法·leetcode
派大星~课堂8 分钟前
【力扣-138. 随机链表的复制 ✨】Python笔记
python·leetcode·链表
cpp_250113 分钟前
P10108 [GESP202312 六级] 闯关游戏
数据结构·c++·算法·动态规划·题解·洛谷·gesp六级
Lzh编程小栈17 分钟前
数据结构与算法之队列深度解析:循环队列+C 语言硬核实现 + 面试考点全梳理
c语言·开发语言·汇编·数据结构·后端·算法·面试
AbandonForce19 分钟前
模拟实现vector
开发语言·c++·算法
少许极端24 分钟前
算法奇妙屋(四十二)-贪心算法学习之路 9
学习·算法·贪心算法
CoderCodingNo25 分钟前
【NOIP】1998真题解析 luogu-P1010 幂次方 | GESP四、五级以上可练习
算法
py有趣31 分钟前
力扣热门100题之最小覆盖子串
算法·leetcode
汀、人工智能33 分钟前
[特殊字符] 第102课:添加与搜索单词
数据结构·算法·均值算法·前缀树·trie·添加与搜索单词