微软100题(94)找出数组中长度最长的等差数列
2015-06-17 14:41
183 查看
题目:求随机数构成的数组中找到长度大于=3的最长的等差数列
输出等差数列由小到大:
如果没有符合条件的就输出
格式:
输入[1,3,0,5,-1,6]
输出[-1,1,3,5]
思路:首先对数组元素进行排序,取两个元素,便知道方差,依次加上2*diff 3*diff直到没在整个数组里面为止,便得到一个长度,不断更新这个长度 取得两个元素a[0] 第二个a[1].。。。a[n-1] ; a[1] 第二个a[2]...a[n-1]
参考http://www.cnblogs.com/xinxianshi/archive/2011/08/16/2157253.html
分析:
基本算法思路(采用动态规划思想):首先,只要得到数列的公差和一个首项就可以确定一个等差数列,因此我们要寻找最长等差数列的公差以及首项。其次,为了方便查找公差和首项,我们应该将原数组进行由小到大排序,这样各两数之间的公差也是成递增形势的,这样我们就可以避免回溯查找首项。
因此,在搜寻公差及首项的过程中,我们可以分两三个决策阶段:
1、如果公差为0,应该做何处理。
2、如果公差不为0,应该做何处理。
3、如果找到的数列长度是当前最长的做相应的处理
针对以上情况,我们应该选择一种合适的数据结构——平衡排序树,stl中的set,map,mutiset,multimap是以红黑树结构为形势的容器,无疑是非常合适的,根据题目情况,可能存在具有相同元素的数组,因此我们选择multiset,这样无论我们对数据进行插入排序,查找都是比较高效的,因此总体上是可以满意的。
输出等差数列由小到大:
如果没有符合条件的就输出
格式:
输入[1,3,0,5,-1,6]
输出[-1,1,3,5]
思路:首先对数组元素进行排序,取两个元素,便知道方差,依次加上2*diff 3*diff直到没在整个数组里面为止,便得到一个长度,不断更新这个长度 取得两个元素a[0] 第二个a[1].。。。a[n-1] ; a[1] 第二个a[2]...a[n-1]
参考http://www.cnblogs.com/xinxianshi/archive/2011/08/16/2157253.html
分析:
基本算法思路(采用动态规划思想):首先,只要得到数列的公差和一个首项就可以确定一个等差数列,因此我们要寻找最长等差数列的公差以及首项。其次,为了方便查找公差和首项,我们应该将原数组进行由小到大排序,这样各两数之间的公差也是成递增形势的,这样我们就可以避免回溯查找首项。
因此,在搜寻公差及首项的过程中,我们可以分两三个决策阶段:
1、如果公差为0,应该做何处理。
2、如果公差不为0,应该做何处理。
3、如果找到的数列长度是当前最长的做相应的处理
针对以上情况,我们应该选择一种合适的数据结构——平衡排序树,stl中的set,map,mutiset,multimap是以红黑树结构为形势的容器,无疑是非常合适的,根据题目情况,可能存在具有相同元素的数组,因此我们选择multiset,这样无论我们对数据进行插入排序,查找都是比较高效的,因此总体上是可以满意的。
#include <iostream> #include <ctime> #include <set> using namespace std; void show_longest_seq(const multiset<int>& myset) { int maxLength = 0, curr_pos = 0, curr_d = 0, counter=0,i=0; //一些辅助变量 int d_result, a1_result; //存储最长等差数列的公差以及首项 multiset<int>::const_iterator set_it1,set_it2; /* (主题)寻找长度最长的等差数列,最坏情况下时间复杂度为O(n^3) */ for(set_it1 = myset.begin(); set_it1 != myset.end();) { for(set_it2=set_it1,set_it2++; set_it2 != myset.end();)//第二层循环从set_it1所指的下一个元素开始遍历 { curr_d = *set_it2 - *set_it1; //算得当前公差,注意由于set为自排序容器,从小到大排列,所以curr_d恒为正 if(curr_d == 0) // 如果公差为0 { counter = myset.count(*set_it1); set_it2 = myset.upper_bound(*set_it1);//(优化项)跳过与set_it1相等的元素 } else { counter = 2; //(优化项)最小长度要求要不小于所以直接从开始累加 while(myset.find(*set_it1 + counter*curr_d) != myset.end()) //计算数列项个数 ++counter; set_it2 = myset.upper_bound(*set_it2);// (优化项)跳过与*set_it2相等的元素 } if(counter > maxLength) //如果新数列长度大于maxLength { d_result = curr_d; a1_result = *set_it1; maxLength = counter; } } curr_pos += myset.count(*set_it1); //计算第一层循环遍历到的当前位置 if(myset.size()-curr_pos < maxLength) // (优化项)如果集合中剩下的元素小于最大数列长度,就退出循环 break; set_it1 = myset.upper_bound(*set_it1); //下一次set_it1 的位置,并跳过相同元素 } /* 打印最长等差数列 */ if(maxLength <= 2) { cout<<"longest_seq:[0,0]"<<endl; } else { cout<<"longest_seq:"; for(i = 0; i<maxLength; i++) cout<<*(myset.find(a1_result + i*d_result))<<' '; cout<<endl; } } //Blog:http://blog.csdn.net/zhanxinhang //// test in main int main() { int a[]={1,3,0,5,-1,6}; multiset<int> myset; myset.insert(a,a+6); show_longest_seq(myset); cout<<endl; int l; srand((unsigned)time(NULL)); for(int j = 0; j < 5; j++) { myset.clear(); cout<<"input:[ "; l=rand()%10; for(int i = 0; i < l; ++i) { int element = rand()%10; myset.insert(element); cout<<element<<' '; } cout<<']'<<endl; show_longest_seq(myset); cout<<endl; } return 0; }
相关文章推荐
- 如何做一个好的产品数据
- In person Which i desire class just one excellent seeing that is it doesn't solely imitation wristwatches value taking
- 获取电话归属地
- 最常用的SAT数学题解答方法分享
- 在myeclipse中用maven进行项目的打包时出现内存泄露问题
- 今天开通CSDN,记录DBA学习之路
- HDU3939 Sticks and Right Triangle 毕达哥拉斯三元组+容斥原理
- 微软100题(93)找出数组中比左边的大比右边的小的元素
- 去掉mysql重复的索引
- salt 001
- PEP 0008 -- Style Guide for Python Code
- FAQ13878][Audio APP]收音机 APP 添加耳机hook键,以实现播放、暂停的功能
- PHP学生笔记:PHP中的面向对象编程
- how to print the spend time of one function
- iOS开发内存管理
- iOS中Foundation框架NSString基本用法总结
- adb不响应
- Redis学习第四课:Redis List类型及操作
- 神奇:java中float,double,int的值比较运算
- Python实现的彩票机选器实例