依稀记得见到此题是在校园招聘的笔试题目上,也记得当时的感觉是一头雾水,完全不懂这个题目在干什么。

时间如流水,转眼已工作了一年,工作也阴差阳错的换了一个。偶然间看到这个题目,竟猛然间想起学校时的自己,背着书包,阳光,图书馆,那时自己也不喜欢研究这样的问题,天天在数学问题里泡着,什么算子,理想环的,拓扑的,可以那么没心没肺的只去学习自己喜欢的东西。

扯远了,看到这个问题,仔细想了下,想了种解决的方法,google了一下,发现博客园里有篇文章类似,却又编译不过而且一点注释没有。。。

贴下自己的代码,大家看下,哪里不对的地方请指出。

想想真的挺感谢之前的公司的,接纳了我这个小菜鸟,同时让我成长,为一个大菜鸟^_^

先考虑下简单情况并抽象下问题,珠子改为线性的而不是环,用数组表示,内容为其颜色(用数字表示),则表示为在该数组里找到最小的连续的区间,使得包含所有的数字。

想法是这样的:

先从index=0处搜索,每检查一颗珠子,响应的颜色数量+1,如果是新的颜色则总颜色数+1.

当颜色总数为n时,找到第一个满足条件的连续序列。

1.从该序列起始处搜索,若搜索处的颜色数量不为1,则表明该串还有别的珠子有该颜色,继续往前搜索并更新该序列,起始索引位置+1.

若搜索处颜色数量为1,停止搜索。

2。比较最佳序列长与当前序列长,更新最佳序列。记录当前序列起始位置。

从第一个满足条件的序列继续index++,并检查1,2条件。

//#######################################################################
//# Author: izualzhy@163.com
//# 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: izualzhy@163.com
//# 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