今夜冥王星有雪

导航

查找第一个不重复的字符问题

查找第一个不重复的字符问题

最近去面了一次试,最后面到一次算法题。说实话,以前去面试很少面到算法题,可能和面试的职位有关的。

相当常见的题目,说是找出一堆数字中第一个出现的不重复的数字。当时没理解清题目,想成了是只有一个不重复的数字。后来面试官跟我说明清楚了题目之后,瞬间没了啥思路,也没答好。后来回去路上一想,感觉也相当简单。

这个题目原题是 “找出一个字符串(只包含英文,不考虑中文等字符问题)中第一个不重复的数字”。

如果不做限制,很容易想到的方法是:从头开始遍历一下字符串,针对每个字符再从开开始查找是否有重复的,找到第一个整个字符串中没有重复的字符。当然时间复杂度为 O(n2),肯定不是最优解。

比较普遍的方法是牺牲一定的空间复杂度,用一个数组暂存一下字符串中每个字符出现的次数,再重新从头开始遍历字符串,找到次数为 1 的字符返回。

代码如下:

func searchFirstNotDuplicatedChar(str string) string {
	cnts := make([]int, 256)

	for _, s := range str {
		cnts[s]++
	}

	for _, s := range str {
		if cnts[s] == 1 {
			return string(s)
		}
	}

	return ""
}

复杂度就是遍历了两次字符串,时间复杂度为 O(n)。已经相当可以了。

当然面试官给我出的原题是一堆数字,不是字符串(这和我面试时提到的以往的工作有关,处理批量数据)。因为我们知道英文字符处于 ASCII 码表中很容易做对应。而数字类数据的话因为不知道范围,很难用一个数组来做存储对应,所以这个我们可以考虑用一个 Map。我们知道 Hash 方法是很快速的,所以几乎不存在什么性能问题。

这个为了简便,只考虑了整形 int 类型的数据。

func findFirstNotDuplicatedInt(nums []int) int {
	cnts := make(map[int]int)

	for _, num := range nums {
		cnts[num]++
	}

	for _, num := range nums {
		if cnts[num] == 1 {
			return num
		}
	}

	return -1
}

就稍微改了一下,依然是 O(n)。差不多是这个。据说还有使用位运算的算法可以做到,暂时没研究,感觉这样已经很不错了。

对于算法题,面试和自己平常在电脑上做,感觉真是不一样的。面试中包含各种不确定的因素,而且人也容易产生紧张感,往往有些平常很容易想到的东西面试中就犯迷糊了。复杂的算法由于平时几乎不太用到,也是看过就很容易忘。所以我觉得培养一种对于算法的直觉相当重要。

posted on 2018-07-23 00:52  alfred_zhong  阅读(2262)  评论(0编辑  收藏  举报