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

有没有遇到过这样的数字序列:
[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 小时前
Leetcode hot 100(day 3)
算法·leetcode·职场和发展
战族狼魂3 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
xyliiiiiL4 小时前
ZGC初步了解
java·jvm·算法
杉之4 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
爱的叹息4 小时前
RedisTemplate 的 6 个可配置序列化器属性对比
算法·哈希算法
hycccccch5 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
独好紫罗兰5 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
每次的天空6 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
天天向上杰6 小时前
面基JavaEE银行金融业务逻辑层处理金融数据类型BigDecimal
java·bigdecimal
请来次降维打击!!!6 小时前
优选算法系列(5.位运算)
java·前端·c++·算法