m个珠子共n种颜色,找出包含n种颜色的最短连续片段

本文介绍了一种高效算法,用于在给定的珠子串中找到包含所有颜色的最短子串。通过使用双指针技巧和队列数据结构,算法能够优化时间复杂度并提供解决方案。

转载:http://blog.youkuaiyun.com/zhccl/article/details/8044449

分享百度一个面试题:


有一串珠子首尾不相连,总共N个,这些珠子总共有M种颜色,在这串珠子里面找到最短的连续珠子子串,使子串出现所有的M种颜色。

毫无疑问,这个可以用暴力破解,N^2 时间效率可以解决,面试官百分之一千会让你优化。


设置两个位置指针 t 和 h ,代表出现所有颜色的联系珠子的子串的起始位置和最后位置

如果能保证 h 所指的位置的珠子是第一次出现,如果尽量将 t 向前移动,得到的 t - h 的子串就是以 h 结尾子串的最短子串

在什么情况下,能向前移动 t 呢?

如果说 t 位置所指的颜色,在 t+1~h之间还有出现,就能保证 t 可以向前移一个位置


比如珠子是:11232324314,最短子串是 2431

第一次找到所有颜色的子串是 11232324,子串最后颜色 4 是子串中唯一出现的颜色

此时的 t 指向 第一个 1,而 1 在后面还有出现,可以将 t 向前移动一个 即得到更短的子串 1232324

还能再移吗?不能了,因为此时 颜色 1 在这个子串中唯一,也就是说 以 h(指向子串最后一个4)结尾的子串,要包含所有颜色1234那么最短的子串是 1232324

得到的这个子串是所有包含所有颜色子串最短的吗?也不是,那么我们该怎么找到下一个包含所有颜色的子串?

假设,我删除掉获得的子串 1232324 的第一个 颜色 1,再从后边的珠子里找到颜色 1 ,即 23232431,此时 最后的颜色 1 又是这个子串唯一的颜色了

同样的方法,只要后面还有和 当前 t 指向的颜色,那么就移动 t 直到无法移动,过程如下:

t 指向 23232431,2 在后面的 3232431 中还有出现,向前移动 t

t 指向 3232431,3  在后面的 232431 中还有出现,向前移动 1

t 指向 232431,2 在后面的 32431 中还有出现,向前移动 1

t 指向 32431,3 在后面的2431 中还有出现,向前移动 1

t指向 2431,2 在后面的431中没有出现了,不能向前移动了

此时得到的子串就是最短子串,因为 子串长度==颜色种数


  1. //M长度队列有N种颜色,找到包含所有颜色的最短字串  
  2. int FindFullColor(int arr[],int n,int m){  
  3.     //C用来存储 每一种颜色出现的次数,C[0]不用  
  4.     //颜色用m来表示,m代表有颜色:1,2,3,...,m  
  5.     //即在arr[n]中找出同时出现 1,2,...,m 的最短字串  
  6.     int *c=(int *)malloc((m+1)*sizeof(int));  
  7.     memset(c,0,(m+1)*sizeof(int));  
  8.   
  9.     int min=n;  
  10.     int h=0,t=0,ctr=m;  
  11.   
  12.     while(1){  
  13.         while( ctr>0 && h<n ){  
  14.             if(c[arr[h]]==0){  
  15.                 ctr--;  
  16.             }  
  17.             c[arr[h]]++;  
  18.             h++;  
  19.         }  
  20.         //已经结束但依然没找齐颜色  
  21.         if(h>=n){  
  22.             break;  
  23.         }  
  24.         while(1){  
  25.             c[arr[t]]--;  
  26.             if(c[arr[t]]==0){     
  27.                 break;  
  28.             }  
  29.             //如果c[arr[t]]--之后,不为0,代表在 t 后面还有 arr[t] 的颜色  
  30.             //所以当前 t 不是最短的,至少比后面那个长  
  31.             t++;  
  32.         }  
  33.         if(h-t<min){  
  34.             min=h-t;  
  35.             //更新之后打印  
  36.             //如果最后只打印最短的,则可以把 min,t,h 同时存储  
  37.             for(int i=t;i<h;i++){  
  38.                 printf("%d",arr[i]);  
  39.             }  
  40.             printf("\n");  
  41.         }  
  42.   
  43.         //删除颜色直到某个颜色为,这个颜色在 t-h 之间没有了  
  44.         //这就需要在 h-n 之间再找到这种颜色  
  45.         t++;  
  46.         ctr++;  
  47.     }  

在Halcon中计数算盘上不同颜色珠子的个数,你可以按照以下步骤进行: 1. **图像读取和预处理**: 使用`h_image_read`读取包含算盘图像的文件,然后可能需要进行灰度化 (`h_image_gray`) 或者增强对比度 (`h_image_contrast_stretch`),以便更好地处理颜色珠子。 2. **颜色分割**: - 针对四种颜色(粉色、蓝色、绿色和黄色),创建对应的阈值或者色彩直方图模板(`h_color_histogram`),然后使用`h_select_color_components`或者`h_color_segment`函数进行颜色分段,得到每个颜色的掩模图像。 3. **矩形框选取**: - 确定珠子在图像中的大致位置,可以使用`h_min_max_search`寻找轮廓或者基于珠子尺寸的边界框。针对每个颜色,找出相应掩模对应区域的边缘坐标,形成矩形框。 4. **珠子计数**: 在每个颜色的掩模图像上,使用`h_count`函数计算每个矩形区域内像素点的数量,即珠子个数。 5. **结果显示**: 后,在图像左上角,你可以使用`h_rectangle_draw`画出每个颜色的矩形框,并在其旁边使用`h_text_line2d`写入各自颜色的珠子个数。 6. **整合代码**: 将上述步骤集成到个循环中,以便处理所有珠子颜色。 以下是简化版伪代码示例: ```python image = h_image_read("your_image_file") gray_image = h_image_gray(image) for color in ['pink', 'blue', 'green', 'yellow']: # 获取该颜色的阈值或模板 color_mask = get_color_mask(color) # 寻找并计数珠子 count = h_count(gray_image, color_mask, ...) # 绘制矩形框和结果显示 draw_rectangle(image, color) display_text(image, f"{color}: {count}", top_left=True) image_show(image) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值