依稀记得见到此题是在校园招聘的笔试题目上,也记得当时的感觉是一头雾水,完全不懂这个题目在干什么。
时间如流水,转眼已工作了一年,工作也阴差阳错的换了一个。偶然间看到这个题目,竟猛然间想起学校时的自己,背着书包,阳光,图书馆,那时自己也不喜欢研究这样的问题,天天在数学问题里泡着,什么算子,理想环的,拓扑的,可以那么没心没肺的只去学习自己喜欢的东西。
扯远了,看到这个问题,仔细想了下,想了种解决的方法,google了一下,发现博客园里有篇文章类似,却又编译不过而且一点注释没有。。。
贴下自己的代码,大家看下,哪里不对的地方请指出。
想想真的挺感谢之前的公司的,接纳了我这个小菜鸟,同时让我成长,为一个大菜鸟^_^
先考虑下简单情况并抽象下问题,珠子改为线性的而不是环,用数组表示,内容为其颜色(用数字表示),则表示为在该数组里找到最小的连续的区间,使得包含所有的数字。
想法是这样的:
先从index=0处搜索,每检查一颗珠子,响应的颜色数量+1,如果是新的颜色则总颜色数+1.
当颜色总数为n时,找到第一个满足条件的连续序列。
1.从该序列起始处搜索,若搜索处的颜色数量不为1,则表明该串还有别的珠子有该颜色,继续往前搜索并更新该序列,起始索引位置+1.
若搜索处颜色数量为1,停止搜索。
2。比较最佳序列长与当前序列长,更新最佳序列。记录当前序列起始位置。
从第一个满足条件的序列继续index++,并检查1,2条件。
//####################################################################### //# Author: [email protected] //# Created Time: 2012/3/15 14:15:46 //# File Name: pearls.cpp //# Description: //####################################################################### #include <iostream> using namespace std; #define MAXN 10 int colors[MAXN];//record the counter of one color int colorsCounter; void find(int arr[],int len, int colorsNeed) { int bestStartIndex = 0; int bestLen = len; int lastStartIndex = 0; for ( int i=0; i<len; ++i) { if (!colors[arr[i]]) colorsCounter++; colors[arr[i]]++; if (colorsCounter==colorsNeed) { int j = lastStartIndex; while (colors[arr[j]]>1) { colors[arr[j]]--; ++j; } if (i-j+1<bestLen) { bestStartIndex = j; bestLen = i-j+1; if (bestLen==colorsNeed) break; } lastStartIndex = j; } } cout << bestStartIndex << endl; cout << bestLen << endl; for (int i=bestStartIndex; i<bestLen+bestStartIndex; ++i) cout << arr[i] << " "; cout << endl; } int main() { int arr[] = {1,2,3,3,2,1,4,1,3,4,5,6,2,3,4,1,5,2,3,4}; int m = sizeof(arr)/sizeof(arr[0]); for ( int i=0; i<m; ++i) cout << arr[i] <<" "; cout << endl; int n = 6; find(arr,m,n); return 0; } 输出:
1 2 3 3 2 1 4 1 3 4 5 6 2 3 4 1 5 2 3 4
7
6
1 3 4 5 6 2
如果是环的话多了一遍循环:
//####################################################################### //# Author: [email protected] //# Created Time: 2012/3/15 14:15:46 //# File Name: pearls.cpp //# Description: //####################################################################### #include <iostream> using namespace std; #define MAXN 10 int colors[MAXN];//record the counter of one color int colorsCounter; void find(int arr[],int len, int colorsNeed) { int bestStartIndex = 0; int bestLen = len; int lastStartIndex = 0; int firstFoundEnoughPearls = len; for ( int i=0; i<len; ++i) { if (!colors[arr[i]]) colorsCounter++; colors[arr[i]]++; if (colorsCounter==colorsNeed) { firstFoundEnoughPearls = i; } if (firstFoundEnoughPearls!=len) { int j = lastStartIndex; while (colors[arr[j]]>1) { colors[arr[j]]--; ++j; } if (i-j+1<bestLen) { bestStartIndex = j; bestLen = i-j+1; if (bestLen==colorsNeed) break; } lastStartIndex = j; } } for ( int i=0; i<firstFoundEnoughPearls; ++i) { if (!colors[arr[i]]) colorsCounter++; colors[arr[i]]++; int j = lastStartIndex; while (colors[arr[j]]>1) { colors[arr[j]]--; ++j; } if (i-j+1+len<bestLen) { bestStartIndex = j; bestLen = i-j+1+len; if (bestLen==colorsNeed) break; } lastStartIndex = j; } int offset = bestStartIndex; for (int i=0; i<bestLen;) { cout << arr[i+offset] << " "; ++i; if (i+offset>=len) offset = 0-i; } cout << endl; } int main() { int arr[] = {1,2,3,3,2,1,4,1,2,3,2,6,4,5,2,6,2,3,4,1,2,5,2,3,4,5,6}; int m = sizeof(arr)/sizeof(arr[0]); int n = 6; find(arr,m,n); return 0; }
输出:
2 3 4 5 6 1