给一个很长的字符串str 还有一个字符集比如"abc" 找出str 里包含"abc"的最短子串。要求O(n)

在面试100题中看到了这个题,实现下:


题目:给一个很长的字符串str ,还有一个字符集比如"abc" ,找出str 里包含"abc"的最短子串。要求O(n)。

例如:字符串str:abdcaabcx,字符集dest:abc,那么最短子串就是abc。

实现思路是在july大神的博客上看到的http://blog.csdn.net/v_july_v/article/details/6126444

用两个变量 front,rear 指向一个的子串区间的头和尾(当然,开始时front和rear都指向字符串开始处)。 

用一个int cnt[255]={0}记录当前这个子串里字符集a,b,c各自的个数,一个变量count记录字符集里有多少个了。 

rear 一直加,更新cnt[]和count的值,直到count等于字符集个数。

然后front++,直到cnt[]里某个字符个数为0(front 开始的部分有可能和后面的重复,所以front要加到某个字符个数为0), 这样就找到一个符合条件的字串了,继续下去,可以求出所有符合条件的串,同时可以求出满足条件最短子串。

用Java实现的代码如下:


	public static void MinSubString(String src, String dest) {
		int min = Integer.MAX_VALUE;// 找最短子串
		int minfront = 0;// 最短子串开始位置
		int minrear = 0;// 最短子串结束位置
		int front, rear;
		front = rear = 0;
		int count = 0;
		int hashtable[] = new int[256];
		int cnt[] = new int[256];
		for (int i = 0; i < dest.length(); i++) {
			hashtable[dest.charAt(i)] = 1;
		}
		while (rear < src.length()) {
			if (hashtable[src.charAt(rear)] == 1) {// rear当前字符在字符集中
				// 判断是否是本子串中第一次检索到此字符,由count统计字符集中已出现的字符数
				if (cnt[src.charAt(rear)] == 0) {
					count++;
					cnt[src.charAt(rear)]++;
					if (count == dest.length()) {// 字符集中的字符在本子串中都已检索到
						while (true) {
							if (hashtable[src.charAt(front)] == 1) {// front当前字符在字符集中
								cnt[src.charAt(front)]--;
								// 字符集中某个字符为0,此时front到rear所指字符串即为符合条件的子串
								if (cnt[src.charAt(front)] == 0) {
									for (int i = front; i <= rear; i++) {
										System.out.print(src.charAt(i));
									}
									System.out.println();
									if (rear - front + 1 < min) {
										min = rear - front + 1;
										minrear = rear;
										minfront = front;
									}
									// count不需要清空(赋0),cnt数组也不需要任何操作
									count--;// 因为某个字符为出现次数已经减为0了,所以count--
									front++;// 这个不可少
									break;
								}
							}
							front++;
						}
					}
				} else {
					cnt[src.charAt(rear)]++;
				}
			}
			rear++;
		}
		if (min == Integer.MAX_VALUE) {
			System.out.println("没有找到需要和谐的字符串");
		} else {
			System.out.println("最短字符串是:");
			for (int i = minfront; i <= minrear; i++) {
				System.out.print(src.charAt(i));
			}
			System.out.println();
		}
	}



用src="ab1dkj2ksjf3ae32ks1iji2sk1ksl1223ab;1ik3saj123",dest="123"。

测试了下,输入如下:

1dkj2ksjf3
32ks1
1223
23ab;1
3saj12
123
最短字符串是:
123




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值