🔍 找到数组里的“节奏感”:最长等差子序列

有没有遇到过这样的数字序列:
[3, 6, 9, 12]

你一看就知道:哇,这是一个节奏分明、步步递进的等差数列!

那么问题来了:**如果数组不是这么整齐呢?**比如:

ini 复制代码
int[] arr = {3, 6, 9, 7, 12, 15, 4, 8};

请你找出这个数组中最长的等差子序列,也就是说,一段步伐一致的"节奏段子",长度最长是多少?

🧠 解题思路:把每一对数字看作"舞伴"

我们想象一下,一个数组里的每两个数字 array[j]array[i](其中 j < i)就是在跳舞。

只要这两个数字的"步伐差"(也就是 array[i] - array[j])一样,我们就可以把它们串成一段节奏。

于是我们用一个 Map<Integer, Integer>[] dp 数组来记录每一个以 i 结尾、以某个"步伐差值"跳起来的最长序列长度。

动态规划结构设计

ini 复制代码
Map<Integer, Integer>[] dp = new Map[array.length];
  • dp[i] 表示以 array[i] 结尾的等差子序列,Map 的键是差值 diff,值是长度。
  • 初始化每个 dp[i] 为一个新的 HashMap。

然后,我们从 i = 0n - 1,每次再枚举 j = 0i - 1,做如下事情:

差值计算:

c 复制代码
int diff = array[i] - array[j];

🎯 状态转移:

  • 如果 dp[j] 中没有这个差值,我们从头开始这段舞步(长度为2)。
  • 否则,我们延续这个差值的节奏,长度 +1。
ini 复制代码
if (!dp[j].containsKey(diff)) {
    dp[i].put(diff, 2);
} else {
    dp[i].put(diff, dp[j].get(diff) + 1);
}

更新全局最大值:

ini 复制代码
globalMax = Math.max(globalMax, dp[i].get(diff));

最终代码

ini 复制代码
import java.util.HashMap;
import java.util.Map;

public class LongestArithSequence {

    public int longestArithSequence(int[] array){
        if(array == null || array.length < 2) return 0;

        int globalMax = 0;
        Map<Integer, Integer>[] dp = new Map[array.length];

        for(int i = 0; i < array.length; i++) {
            dp[i] = new HashMap<>();
            for(int j = 0; j < i; j++) {
                int diff = array[i] - array[j];
                dp[i].put(diff, dp[j].getOrDefault(diff, 1) + 1);
                globalMax = Math.max(globalMax, dp[i].get(diff));
            }
        }

        return globalMax;
    }

    public static void main(String[] args) {
        LongestArithSequence las = new LongestArithSequence();
        int[] array = {3, 6, 9, 7, 12, 15, 4, 8};
        System.out.println("Longest arithmetic subsequence length: " + las.longestArithSequence(array));
    }
}

🧩 小结:这道题考察了什么?

  • ✅ 动态规划的状态定义能力
  • ✅ 对"差值"这个维度的抽象能力
  • ✅ 选择合适的数据结构(数组 + HashMap)来降低复杂度

思考

  1. 如果是等比数列,思路要怎么变?
  2. 如何打印出最长的那一段子序列?
  3. 如果数组非常长,比如上万条数据,如何进一步优化空间?
相关推荐
小欣加油2 小时前
leetcode56 合并区间
c++·算法·leetcode·职场和发展
lqqjuly2 小时前
前沿算法深度解析(二)
人工智能·算法·机器学习
wang09072 小时前
自己动手写一个spring之IOC_2
java·后端·spring
来杯@Java3 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
徐小夕3 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
不知名的老吴4 小时前
线程的生命周期之线程“插队“
java·开发语言·python
akunkuntaimei4 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
ANnianStriver4 小时前
PetLumina-02-后端开发与前后端联调
java·ai·sa-token
Hello:CodeWorld4 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法