携程笔试题:一串首尾相连的珠子(m 个),有N 种颜色(N<=10),设计一个算法,取出其中一段,要求包含所有N 中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
思路:先从index=0处搜索,每检查一颗珠子,响应的颜色数量+1,如果是新的颜色则总颜色数+1.
当颜色总数为n时,找到第一个满足条件的连续序列。
1>从该序列起始处搜索,若搜索处的颜色数量不为1,则表明该串还有别的珠子有该颜色,继续往前搜索并更新该序列,起始索引位置+1.
若搜索处颜色数量为1,停止搜索。
2>比较最佳序列长与当前序列长,更新最佳序列。记录当前序列起始位置。从第一个满足条件的序列继续index++,并检查1,2条件。
package test;
public class Ctrip {
int[] colors=new int[10];
int colorsCount=0;
public void find(int[] arr,int len,int colorsNeed){
int bestStartIndex=0;
int bestLen=len;
int lastStartIndex=0;
int firstFoundEnoughPearls=0;
for(int i=0;i<arr.length;i++){
if(colors[arr[i]]==0){
colorsCount++;
}
colors[arr[i]]++;
if(colorsCount==colorsNeed){
firstFoundEnoughPearls=i;
int j=lastStartIndex;
while(colors[arr[j]]>1){
colors[arr[j]]--;
j++;
}
if(bestLen>(i-j+1)){
bestStartIndex=j;
bestLen=i-j+1;
if(bestLen==colorsNeed){
break;
}
}
lastStartIndex=j;
}
}
for(int i=0;i<firstFoundEnoughPearls;i++){
if(colors[arr[i]]==0){
colorsCount++;
}
colors[arr[i]]++;
int j=lastStartIndex;
while(colors[arr[j]]>1){
colors[arr[j]]--;
j++;
}
if(bestLen>(i-j+len+1)){
bestLen=i-j+len+1;
bestStartIndex=j;
if(bestLen==colorsNeed){
break;
}
}
lastStartIndex=j;
}
int offset=bestStartIndex;
System.out.println("bestLen:"+bestLen);
System.out.println("bestStartIndex:"+bestStartIndex);
for(int i=0;i<bestLen;){
System.out.print(arr[i+offset]+" ");
i++;
if((i+offset)>=len){
offset=0-i;
}
}
}
}
package test;
public class TestCtrip {
public static void main(String args[]){
int[] arr={1,2,3,3,2,1,4,2,3,2,6,4,5,2,6,2,3,4,1,2,5,2,3,4,5,6};
int m=arr.length;
int n=6;
Ctrip c=new Ctrip();
c.find(arr, m, n);
}
}