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 小时前
多场景落地复盘:端边云架构无人机智能巡检系统设计与实践
大数据·数据结构·人工智能·科技·架构·无人机·能源
CV-Climber2 小时前
检索技术的实际应用
人工智能·算法
hhzz3 小时前
Tiger AI Platform平台中增加人脸识别功能
图像处理·人工智能·算法·计算机视觉·大模型
从零开始的代码生活_4 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
TsingtaoAI4 小时前
3D高斯泼溅技术发展及其在具身智能领域的应用综述
人工智能·算法·ai·具身智能·高斯泼溅
atunet4 小时前
关于图算法中的连通分量检测与最小割问题7
算法
心运软件5 小时前
银行客户流失预测(Python 完整实战)
算法
邪神与厨二病5 小时前
牛客周赛 Round 153
python·算法
qizayaoshuap7 小时前
# ❌ 井字棋 — 鸿蒙ArkTS Minimax AI算法与博弈系统设计
人工智能·算法·华为·harmonyos