查找首个非重复字符

问题描述:
     编写一个高效的函数,找到字符串中首个非重复字符。
     example:
      total    首个非重复字符是 o

      teeter   首个非重复字符是 r 

 分析:
     最直观也是最容易想到的方式就是对每个字符在字符串中遍历
 一遍,若出现相同的字符则退出遍历,查看下一字符,若遍历完整
 个字符串均为出现相同字符,则表明该字符是首个非重复字符。

程序代码如下:

bool FirstNonRepeated1(std::string str, char &out) {
	for (int i = 0; i < str.length(); ++i) {
		char temp = str[i];
		int j;
		for (j = 0; j < str.length(); ++j) {
			if (i != j && temp == str[j]) {
				break;
			}
		}
		if (j >= str.length()) {
			out = temp;
			return true;
		}
	}
	return false;
}


从以上程序可以看出,其时间复杂度为O(n^2),效率不是很好,如何才能进一步提高它的效率呢?
我们知道数组和散列表的查找时间都是常数(散列表在最坏的情况下是O(n),但平均情况是
O(1))。要想能够快速确定一个字符是否重复,需要按字符来搜缩,这意味着需要用字符作
为下标(在数组中)或键(在散列表中)。在数组或散列表中会存放什么呢?因为不重复的字符
只在字符串中出现一次,所以若存放字符出现的次数,就能确定不重复的字符了。当完成
这项工作,就可在数组或散列表中扫描所有的计数,寻找计数为1的字符,需要主要的是,
此时查找的不重复字符不一定是原来字符串中的第一个不重复字符。解决方法是按照原字符
串顺序进行查找。
程序代码如下:

bool FirstNonRepeated(std::string str, char &out) {
	int flags[128] = {0};
	for (int i = 0; i < str.length(); ++i) {
		int flag = flags[str[i]];
		if (flag == 0) {
			flags[str[i]] = 1;
		} else if (flag == 1) {
			flags[str[i]]++;
		}
	}
	for (int i = 0; i <str.length(); ++i) {
		if (flags[str[i]] == 1) {
			out = str[i];
			return true;
		}
	}
	return false;
}

现在,程序的时间复杂度将为了O(n),但是与改进前相比,增加了空间复杂度,通常这是可取的。

参考:程序员面试攻略 第六章 数组和字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值