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

有没有遇到过这样的数字序列:
[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. 如果数组非常长,比如上万条数据,如何进一步优化空间?
相关推荐
皮皮林5514 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
归去_来兮5 小时前
拉格朗日插值算法原理及简单示例
算法·数据分析·拉格朗日插值
顺风尿一寸7 小时前
从 Java NIO poll 到 Linux 内核 poll:一次系统调用的完整旅程
java
程途知微7 小时前
JVM运行时数据区各区域作用与溢出原理
java
华仔啊10 小时前
为啥不用 MP 的 saveOrUpdateBatch?MySQL 一条 SQL 批量增改才是最优解
java·后端
千寻girling12 小时前
Python 是用来做 AI 人工智能 的 , 不适合开发 Web 网站 | 《Web框架》
人工智能·后端·算法
xiaoye201812 小时前
Lettuce连接模型、命令执行、Pipeline 浅析
java
颜酱15 小时前
一步步实现字符串计算器:从「转整数」到「带括号与优化」
javascript·后端·算法
beata15 小时前
Java基础-18:Java开发中的常用设计模式:深入解析与实战应用
java·后端
Seven9716 小时前
剑指offer-81、⼆叉搜索树的最近公共祖先
java