最长等差数列_最长等差子序列的长度

本文介绍了一种解决寻找整数数组中最长等差子序列问题的方法。通过动态规划,从数组的第一个元素开始,计算每个元素与之前所有元素的差值,根据这些差值更新以当前元素结尾的等差子序列长度。最终,返回最长等差子序列的长度。例如,在数组[20, 1, 15, 3, 10, 5, 8]中,最长等差子序列是[20, 15, 10, 5],长度为4。" 111953470,10546137,使用qemu-img创建与管理虚拟机镜像及快照,"['虚拟机管理', '虚拟机快照', 'qemu', '磁盘管理']
摘要由CSDN通过智能技术生成

问题描述

给定一个整数数组 A,返回A 中最长等差子序列的长度。

输入:[20,1,15,3,10,5,8]

输出:4

解释:最长的等差子序列是 [20,15,10,5]

问题分析

我们要找出最长的等差子序列,则必须要找出所有的等差子序列,然后比较它们的长度,找出最长的。那么,怎么找,才能保证不重复,不遗漏呢?如果你使用动态规划,做过最大子序列和的问题,那么很容易产生灵感,我们可以依次寻找以数组A[i](0=

如何由A[i-1]结尾的所有等差子序列,求出以A[i]结尾的所有等差子序列呢?仔细想想,好像以A[i]结尾的等差子序列,并不见得与以A[i-1]结尾的等差子序列,有多大关系呀?事实也确实如此,A[i]的子序列,甚至都不需要A[i-1]的参与,随便举个例子,4,6,9,8,以8结尾的等差子序列4,6,8与以9结尾的等差子序列6,9,一点关系都没有。A[i]与A[i-1]之所以没有明显的关系,是因为这里的等差子序列,并不要求是连续的,而是可以跳跃存在的。事实上,要求出A[i]结尾的等差子序列,则必须一一算出A[i]与A[0...i-1]的差值,分别与以A[0...i-1]结尾的所有等差子序列的差值作比较,若相等,则以这个差值为key,以相等的这个等差子序列的长度+1作为value,挂到A[i]名下;若不等,那就以差值为key,长度2为value丢到A[i]脚下。如果A[i]那里已经有这个key了,那还得比较新的value与原始value的大小,将大的存进去。在递推的过程中,每次更新A[i]的等差子序列的长度时,顺便更新一下我们要的结果,也就是最长等差子序列的长度,循环结束后,返回这个最长等差子序列的长度,即可。

代码实现

@Test

public void testAdditiveNumber() {

int[] A = {9,37,30,50,67,32,47,44,11,15,4,11,3,12,17,18,25,19,21,17,21,23,70,51,61,21,52,25};

System.out.println("Result: "+new Solution().

longestArithSeqLength(A));

}

class Solution {

public int longestArithSeqLength(int[] A) {

if(A == null){

return 0;

}else if(A.length < 3){

return A.length;

}

int n = A.length;

//以A[i]结尾的所有等差数列的差值和长度 HashMap> diffMap = new HashMap<>();

for(int i=0; i

diffMap.put(i, new HashMap());

}

diffMap.get(0).put(0, 1);

diffMap.get(1).put(A[1] - A[0], 2);

int result = 2;

for(int i=2; i

for(int j=i-1; j>=0; j--) {

//求a[i]与A[0...i-1]的差值 int diff = A[i] - A[j];

//以A[j]结尾的所有等差数列中,存在与A[i]-A[j]相等的差值 if(diffMap.get(j).containsKey(diff)){

//更新以A[i]结尾的等差数列的差值和对应的长度 if(diffMap.get(i).get(diff) == null) {

diffMap.get(i).put(diff, diffMap.get(j).get(diff) + 1);

}else{

diffMap.get(i).put(diff, Math.max(diffMap.get(j).get(diff) + 1, diffMap.get(i).get(diff)));

}

}else{

if(diffMap.get(i).get(diff) == null) {

diffMap.get(i).put(diff, 2);

}

}

//更新最长等差数列的长度 result = Math.max(result, diffMap.get(i).get(diff));

}

}

return result;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值