求随机数构成的数组中找到长度大于或等于3的最长的等差数列
2015-09-13 17:08
357 查看
http://www.cnblogs.com/eric-blog/archive/2012/05/04/2483402.html
输出等差数列由小到大?如果没有符合条件的就输出“NO”。
例如: 输入[1,3,0,5,-1,6] ,输出[-1,1,3,5] 。
要求:时间复杂度,空间复杂度尽量小
解体思路:设随机数为a[],首先排序,
(1)枚举两个数,作为数列中相邻的两个元素Ai,Ai+1,那么可求出等差d=Ai+1-Ai。于是Ai-1=Ai-d,Ai+2=Ai+1+d,因此可以在剩下的数寻找Ai-1,Ai+2是否存在,可以用一个set来维护查找,而数列最长可为n,查找次数最大为n,而查找复杂度为logn,总时间复杂度为O(n^3logn)。复杂度太高,不可取。
(2)动态规划求解。设f[i][j]为以a[i],a[j]结尾的等差数列的最长长度。那么
递归方程为:f[i][j]=max{f[k][i]+1,a[k]-a[i]==a[i]-a[j]},起始条件f[i][j]=1;伪代码如下:
for(int k =0; k <n; k++)
for(int i=k+1;i<n;i++)
for(int j=i+1;j<n;j++)
if(a[k]-a[i] == a[i]-a[j])
f[i][j] = (f[i][j]<f[k][i]+1?f[k][i]+1:f[i][j]);
而,最长长度为即为max{f[i][j]},即以a[i],a[j]结尾,通过一次查找即可求出是那些元素组成的解。复杂度O(n^3)。
(3)枚举等差,将所有差相同的数对(a,b),分别以a,以b作为key,另一个作为值,插入到两个map之中,然后解必然在某一个map之内。于是,枚举每一个map,进行删除操作,比如(a,b)那么下一个值为b+(b-a),前一个值为a-(b-a),分别到两个map中去查找,迭代之。复杂度O(n^2logn)。
解法如下:
1.排序
2.设极值分别为min, max,那么公差范围为(1..max-min);
3.公差d从(1..max-min)循环,求出每次的最长的数列长度f(d)
<根据已得到的数列的长度,还可以进一步减少循环次数>
所以该题目基础是求出一个有序数组中公差为d的最长等差数列。
较简单动态规划:
设等差数列的起始下标为s,当前下标为i,从s到i,构成的最长的等差数列长度为f(s,i),有
f(s,i+1) = f(s,i) +1 ( input[i+1] == input[s] + f(s,i)*d)
f(s,i) ( input[i+1] != input[s] + f(s,i)*d)
最长的数列长度为:
maxLen = max{f(s,i) s∈[1 .. max-min] i∈[0,sizeof(input)) }
算法时间复杂度应为n的平方,空间复杂度可优化至O(1) (代码中为O(n))
代码如下:
点击(此处)折叠或打开
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
void GetSeq(int *input, int size, int d){
if(input == NULL) return;
int result[MAX] = {0};
int startIndex = 0;
int maxLen = 0;
int maxLenStartIndex = -1;
for(;startIndex < size-maxLen; startIndex++){
int i = startIndex;
result[i] = 1;
i++;
for(;i<size;i++){
result[i] = result[i-1];
if(input[i] == input[startIndex] +result[i-1]*d){
result[i]++;
if(result[i]> maxLen){
maxLen = result[i];
maxLenStartIndex = startIndex;
}
}
else if(input[i] > input[startIndex] + result[i-1]*d)
break;
}
}
printf("Max sequence start index: %d, length: %d \n", maxLenStartIndex, maxLen);
}
int main(){
int input[] = {1,3,4,6,7,9,10,12,13,15,16,18,21,24};
GetSeq(input, sizeof(input)/sizeof(int), 3);
}
输出等差数列由小到大?如果没有符合条件的就输出“NO”。
例如: 输入[1,3,0,5,-1,6] ,输出[-1,1,3,5] 。
要求:时间复杂度,空间复杂度尽量小
解体思路:设随机数为a[],首先排序,
(1)枚举两个数,作为数列中相邻的两个元素Ai,Ai+1,那么可求出等差d=Ai+1-Ai。于是Ai-1=Ai-d,Ai+2=Ai+1+d,因此可以在剩下的数寻找Ai-1,Ai+2是否存在,可以用一个set来维护查找,而数列最长可为n,查找次数最大为n,而查找复杂度为logn,总时间复杂度为O(n^3logn)。复杂度太高,不可取。
(2)动态规划求解。设f[i][j]为以a[i],a[j]结尾的等差数列的最长长度。那么
递归方程为:f[i][j]=max{f[k][i]+1,a[k]-a[i]==a[i]-a[j]},起始条件f[i][j]=1;伪代码如下:
for(int k =0; k <n; k++)
for(int i=k+1;i<n;i++)
for(int j=i+1;j<n;j++)
if(a[k]-a[i] == a[i]-a[j])
f[i][j] = (f[i][j]<f[k][i]+1?f[k][i]+1:f[i][j]);
而,最长长度为即为max{f[i][j]},即以a[i],a[j]结尾,通过一次查找即可求出是那些元素组成的解。复杂度O(n^3)。
(3)枚举等差,将所有差相同的数对(a,b),分别以a,以b作为key,另一个作为值,插入到两个map之中,然后解必然在某一个map之内。于是,枚举每一个map,进行删除操作,比如(a,b)那么下一个值为b+(b-a),前一个值为a-(b-a),分别到两个map中去查找,迭代之。复杂度O(n^2logn)。
解法如下:
1.排序
2.设极值分别为min, max,那么公差范围为(1..max-min);
3.公差d从(1..max-min)循环,求出每次的最长的数列长度f(d)
<根据已得到的数列的长度,还可以进一步减少循环次数>
所以该题目基础是求出一个有序数组中公差为d的最长等差数列。
较简单动态规划:
设等差数列的起始下标为s,当前下标为i,从s到i,构成的最长的等差数列长度为f(s,i),有
f(s,i+1) = f(s,i) +1 ( input[i+1] == input[s] + f(s,i)*d)
f(s,i) ( input[i+1] != input[s] + f(s,i)*d)
最长的数列长度为:
maxLen = max{f(s,i) s∈[1 .. max-min] i∈[0,sizeof(input)) }
算法时间复杂度应为n的平方,空间复杂度可优化至O(1) (代码中为O(n))
代码如下:
点击(此处)折叠或打开
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
void GetSeq(int *input, int size, int d){
if(input == NULL) return;
int result[MAX] = {0};
int startIndex = 0;
int maxLen = 0;
int maxLenStartIndex = -1;
for(;startIndex < size-maxLen; startIndex++){
int i = startIndex;
result[i] = 1;
i++;
for(;i<size;i++){
result[i] = result[i-1];
if(input[i] == input[startIndex] +result[i-1]*d){
result[i]++;
if(result[i]> maxLen){
maxLen = result[i];
maxLenStartIndex = startIndex;
}
}
else if(input[i] > input[startIndex] + result[i-1]*d)
break;
}
}
printf("Max sequence start index: %d, length: %d \n", maxLenStartIndex, maxLen);
}
int main(){
int input[] = {1,3,4,6,7,9,10,12,13,15,16,18,21,24};
GetSeq(input, sizeof(input)/sizeof(int), 3);
}
相关文章推荐
- Kotlin语法(其他)
- 出现提示ERROR 1289 The 'InnoDB' feature is disabled; you need MySQL built with 'InnoDB' to have IT working
- Hello JSP!——response对象
- 从cocos2d中导入项目到Android
- HDU 5443 The Water Problem 签到
- 简单工厂模式和工厂方法模式
- mysql中date、datetime、time、timestamp之间的使用
- POJ C++程序设计 编程题#3:计算数列平方和
- android广播的两种方式!
- 日历系统——控制台输入年份和月份,打印该月的日历
- 系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式
- Effective C++——条款35(第6章)
- windowsphone8.1学习笔记之磁贴
- Spring配置Hibernate框架事务
- Javascript高级程序设计第十三章(事件)
- 重构与模式:改善代码三部曲中的第三部
- STC-ISP~发布项目程序使用说明
- Leetcode #3 Longest Substring Without Repeating Characters
- Java订单号生成工具(实现一)基于对象锁
- Unix网络编程中的I/O模型