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;
    }



}
相关推荐
一只齐刘海的猫2 小时前
【Leetcode】找到字符串中所有字母异位词
算法·leetcode·职场和发展
海清河晏1113 小时前
数据结构 | 八大排序
数据结构·算法·排序算法
liulilittle3 小时前
固定数组时间轮的槽过载优化:桶链表与批次执行
网络·数据结构·链表
IronMurphy4 小时前
【算法五十七】146. LRU 缓存
算法·缓存
Irissgwe4 小时前
数据结构-栈和队列
数据结构·c++·c·栈和队列
两片空白4 小时前
数据容器集合set/frozenset
数据结构
凌波粒4 小时前
LeetCode--108.将有序数组转换为二叉搜索树(二叉树)
算法·leetcode·职场和发展
liulilittle4 小时前
KCC:在 BBR 思路上的一次探索
网络·tcp/ip·算法·bbr·通信·拥塞控制·kcc
浦信仿真大讲堂4 小时前
达索系统SIMULIA Abaqus 2026接触和约束的增强新功能介绍
人工智能·python·算法·仿真软件·达索软件
点云侠5 小时前
PCL 生成三棱锥点云
c++·算法·最小二乘法